Consoildate demo and tutorial stuff under demo. Fixes #1169

This commit is contained in:
Paul Lorenz
2023-06-22 23:54:24 -04:00
parent 916c115c37
commit 4eca60e32d
28 changed files with 146 additions and 161 deletions
+6
View File
@@ -2,6 +2,7 @@
## What's New
### Deprecated Binary Removal
This release removes the following deprecated binaries from the release archives.
* `ziti-controller` - replaced by `ziti controller`
@@ -10,6 +11,11 @@ This release removes the following deprecated binaries from the release archives
The release archives now only contain the `ziti` executable. This executable is now at the root of the archive instead of nested under a `ziti` directory.
### Ziti CLI Demo Consolidation
The ziti CLI functions under `ziti learn`, namely `ziti learn demo` and `ziti learn tutorial` have been consolidate under `ziti demo`.
# Release 0.28.4
## Component Updates and Bug Fixes
+2 -2
View File
@@ -111,10 +111,10 @@ A service is an entity that stores metadata about a server application. The `zit
When prompted, select your running edge router `router01`.
```bash
ziti edge tutorial first-service
ziti demo first-service
```
If you prefer, you may read [the first-service tutorial as a web site](../ziti/cmd/tutorial/tutorials/first-service.md)
If you prefer, you may read [the first-service tutorial as a web site](../ziti/cmd/demo/tutorials/first-service.md)
## Further Exploration
+1 -11
View File
@@ -27,7 +27,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/fabric"
"github.com/openziti/ziti/ziti/cmd/install"
"github.com/openziti/ziti/ziti/cmd/templates"
"github.com/openziti/ziti/ziti/cmd/tutorial"
c "github.com/openziti/ziti/ziti/constants"
"github.com/openziti/ziti/ziti/controller"
"github.com/openziti/ziti/ziti/internal/log"
@@ -131,7 +130,6 @@ func NewCmdRoot(in io.Reader, out, err io.Writer, cmd *cobra.Command) *cobra.Com
pkiCommands := NewCmdPKI(out, err)
fabricCommand := fabric.NewFabricCmd(p)
edgeCommand := edge.NewCmdEdge(out, err)
tutorialCmd := tutorial.NewTutorialCmd(p)
demoCmd := demo.NewDemoCmd(p)
opsCommands := &cobra.Command{
@@ -143,14 +141,6 @@ func NewCmdRoot(in io.Reader, out, err io.Writer, cmd *cobra.Command) *cobra.Com
opsCommands.AddCommand(NewCmdLogFormat(out, err))
opsCommands.AddCommand(NewUnwrapIdentityFileCommand(out, err))
learnCommands := &cobra.Command{
Use: "learn ",
Short: "Tutorials and demos to help you learn about Ziti",
}
learnCommands.AddCommand(demoCmd)
learnCommands.AddCommand(tutorialCmd)
installCommands := []*cobra.Command{
install.NewCmdInstall(out, err),
install.NewCmdUpgrade(out, err),
@@ -195,7 +185,7 @@ func NewCmdRoot(in io.Reader, out, err io.Writer, cmd *cobra.Command) *cobra.Com
{
Message: "Learning Ziti",
Commands: []*cobra.Command{
learnCommands,
demoCmd,
},
},
}
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
_ "embed"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"fmt"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"github.com/openziti/ziti/ziti/cmd/common"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"fmt"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"github.com/openziti/ziti/ziti/cmd/common"
+27
View File
@@ -21,6 +21,7 @@ import (
"github.com/openziti/ziti/ziti/cmd/common"
"github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/spf13/cobra"
"time"
)
func NewDemoCmd(p common.OptionsProvider) *cobra.Command {
@@ -60,6 +61,12 @@ func NewDemoCmd(p common.OptionsProvider) *cobra.Command {
},
}
demoCmd.AddCommand(newFirstServiceTutorialCmd(p))
demoCmd.AddCommand(newPlainEchoServerCmd(p))
demoCmd.AddCommand(newPlainEchoClientCmd(p))
demoCmd.AddCommand(newZitiEchoClientCmd(p))
demoCmd.AddCommand(newZitiEchoServerCmd(p))
agentCmd.AddCommand(echoServerAgentCmd)
echoServerAgentCmd.AddCommand(NewAgentEchoServerUpdateTerminatorCmd(p))
@@ -81,3 +88,23 @@ func NewDemoCmd(p common.OptionsProvider) *cobra.Command {
return demoCmd
}
type TutorialOptions struct {
ControllerUrl string
Username string
Password string
NewlinePause time.Duration
AssumeDefault bool
}
func (self *TutorialOptions) GetControllerUrl() string {
return self.ControllerUrl
}
func (self *TutorialOptions) GetUsername() string {
return self.Username
}
func (self *TutorialOptions) GetPassword() string {
return self.Password
}
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var clientScriptSource []byte
type client struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var multiRouterTunnelerHostedScriptSource []byte
type multiRouterTunnelerHosted struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var multiSdkHostedScriptSource []byte
type multiSdkHosted struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var multiTunnelerHostedScriptSource []byte
type multiTunnelerHosted struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var routerTunnelerBothSidesScriptSource []byte
type routerTunnelerBothSides struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var singleRouterTunnelerHostedScriptSource []byte
type singleRouterTunnelerHosted struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var singleSdkHostedScriptSource []byte
type singleSdkHosted struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var updateConfigAddressableSource []byte
type updateConfigAddressable struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"github.com/openziti/ziti/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/tutorial"
"github.com/spf13/cobra"
"time"
)
@@ -33,7 +32,7 @@ var updateConfigHASource []byte
type updateConfigHA struct {
api.Options
tutorial.TutorialOptions
TutorialOptions
interactive bool
}
@@ -2,12 +2,18 @@
Hello. In this tutorial we’re going to go explore services, identities and polices.
Please note: this tutorial can be run interactively, by running 'ziti edge tutorial first-service'. It can also be viewed as a web page [here](https://github.com/openziti/ziti/blob/release-next/ziti/cmd/tutorial/tutorials/first-service.md). It may be convenient to be able to view both at the same time. The interactive version will save you a lot of typing or copy/pasting, but content may be easier to read in a web-browser.
Please note: this tutorial can be run interactively, by running 'ziti demo first-service'. It can also be viewed as a web
page [here](https://github.com/openziti/ziti/blob/release-next/ziti/cmd/demo/tutorials/first-service.md). It may be convenient to be able to view both at the same time. The interactive version
will save you a lot of typing or copy/pasting, but content may be easier to read in a web-browser.
<!---action:pause -->
## Goals
Let’s say you’re the founder of CloudEcho, the number one provider of echo services. When someone needs to hear back what they’ve said, you are here to make that happen. Any way that a customer needs an echo, be it TCP, UDP or HTTP based echo services, you’ve got them covered. You’ve decided to try integrating Ziti into your services and clients. We’re going to look at a few different ways to do that integration and explore different areas of the Ziti model to build an understanding of how to provide and consume services. In this tutorial we’re going look at how to Zitify the HTTP echo service.
Let’s say you’re the founder of CloudEcho, the number one provider of echo services. When someone needs to hear back what they’ve said, you are here to make that happen. Any way that a customer needs
an echo, be it TCP, UDP or HTTP based echo services, you’ve got them covered. You’ve decided to try integrating Ziti into your services and clients. We’re going to look at a few different ways to do
that integration and explore different areas of the Ziti model to build an understanding of how to provide and consume services. In this tutorial we’re going look at how to Zitify the HTTP echo
service.
<!---action:pause -->
@@ -38,7 +44,8 @@ If your session times out you can run ziti edge login again.
Great, now that we’re logged in, let’s find our local edge router.
Note that this tutorial assumes that you’ve got an edge router running on the same machine as this tutorial. We'll be using localhost when telling the edge router how to connect to the tutorial services. If you don’t have an edge router running locally, please add one now.
Note that this tutorial assumes that you’ve got an edge router running on the same machine as this tutorial. We'll be using localhost when telling the edge router how to connect to the tutorial
services. If you don’t have an edge router running locally, please add one now.
```action:select-edge-router
Pick the name of an edge router to use. It will be referenced in this tutorial as ${edgeRouterName}
@@ -46,7 +53,8 @@ Pick the name of an edge router to use. It will be referenced in this tutorial a
### Cleanup Tutorial Entities
Finally, in case you've run this tutorial before or have done other experimentation with this system the tutorial may not run cleanly. To ensure a clean run we're going to clean up any entities that would conflict with entities created as part of this tutorial.
Finally, in case you've run this tutorial before or have done other experimentation with this system the tutorial may not run cleanly. To ensure a clean run we're going to clean up any entities that
would conflict with entities created as part of this tutorial.
```action:ziti
ziti edge delete service echo
@@ -58,7 +66,8 @@ ziti edge delete service-edge-router-policies where true
# Setting up the Echo Service
We want to run our echo service over Ziti. We need to create various entities in Ziti for this to work, but the first is the service itself. The most important property of a Ziti service is its name. The service name is similar to a DNS name. When we connect to a service or host a service, we do so by name.
We want to run our echo service over Ziti. We need to create various entities in Ziti for this to work, but the first is the service itself. The most important property of a Ziti service is its name.
The service name is similar to a DNS name. When we connect to a service or host a service, we do so by name.
## Creating the Echo Service
@@ -82,13 +91,13 @@ So, now Ziti has an echo service, but that service doesn’t go anywhere, and we
### Plain Echo Service
Let’s start by assuming we don’t want to make any changes to our server software yet. We’re just going to run an echo server which uses the standard library facilities. Let's start that service now. The source can be found [here](../plain_echo_server.go).
Let’s start by assuming we don’t want to make any changes to our server software yet. We’re just going to run an echo server which uses the standard library facilities. Let's start that service now.
The source can be found [here](../plain_echo_server.go).
<!---action:show src=plain_echo_server.go highlight=go-->
```action:run-plain-echo-server
ziti edge tutorial plain-echo-server
ziti demo plain-echo-server
```
The output for this service will be prefixed with plain-http-echo-server. The service is running on port ${port}. We can hit this service with a browser at
@@ -106,14 +115,16 @@ The source for the plain client code is very simple, and can be found here: [her
Let's run it and see what the output looks. At this point, we're not sending any traffic over the Ziti network.
```action:ziti templatize=true colorStdOut=false
ziti edge tutorial plain-echo-client --port ${port} trees are tall
ziti demo plain-echo-client --port ${port} trees are tall
```
<!---action:pause -->
### Terminators Overview
Now that we’ve got the service running, we can tell Ziti how to connect to it. We do that by creating a terminator for the service. A terminator represents an off ramp from the Ziti fabric. When we make a connection through Ziti to a service, the fabric will select a terminator to which traffic will be routed for that connection. For some types of terminators, each connection to the service will result in a new connection from the router to the hosting application. For others, an existing connection between the router and the hosting application will be used.
Now that we’ve got the service running, we can tell Ziti how to connect to it. We do that by creating a terminator for the service. A terminator represents an off ramp from the Ziti fabric. When we
make a connection through Ziti to a service, the fabric will select a terminator to which traffic will be routed for that connection. For some types of terminators, each connection to the service will
result in a new connection from the router to the hosting application. For others, an existing connection between the router and the hosting application will be used.
### Creating the Terminator
@@ -121,7 +132,8 @@ Let's create the terminator. The arguments to the create terminator command are:
1. **echo**: The service we’re creating the terminator for
1. **${edgeRouterName}**: The edge router we want to use to connect to the application server
1. **tcp:localhost:${port}**: The application server address. The format is protocol:hostname-or-ip:port. The protocol can be any of tcp, udp or tls. This address is what the edge router will try to make a
1. **tcp:localhost:${port}**: The application server address. The format is protocol:hostname-or-ip:port. The protocol can be any of tcp, udp or tls. This address is what the edge router will try to
make a
connection to when someone uses the service.
```action:ziti templatize=true
@@ -140,12 +152,16 @@ ziti edge list terminators 'service.name="echo"'
# Client Application
In order to use the echo service, we need a client application. Our application could embed a Ziti SDK, but unmodified applications can also access Ziti services using a tunneler application. See [Tunnelers](https://openziti.github.io/ziti/clients/tunneler.html) for more information. Even though we're not covering tunnelers here, they are built with the Ziti SDKs. Therefore, all the following setup and configuration applies to them.
In order to use the echo service, we need a client application. Our application could embed a Ziti SDK, but unmodified applications can also access Ziti services using a tunneler application.
See [Tunnelers](https://openziti.github.io/ziti/clients/tunneler.html) for more information. Even though we're not covering tunnelers here, they are built with the Ziti SDKs. Therefore, all the
following setup and configuration applies to them.
<!---action:pause -->
## SDK Client
Let's take a look at our SDK client code (viewable [here](../ziti_echo_client.go)). If you compare it with the plain version, you'll notice the actual client code is very similar. The main differences are
Let's take a look at our SDK client code (viewable [here](../ziti_echo_client.go)). If you compare it with the plain version, you'll notice the actual client code is very similar. The main
differences are
1. We have to load our configuration, so that we can initialize a Ziti Context
2. We have to intercept the Dial in the HTTP client, so we can send it through Ziti
@@ -159,26 +175,33 @@ We can't actually run it yet, because we don't have a configuration for it. As a
# Identity Setup
The main thing our client needs to connect to the Ziti network is an identity. One of the primary functions of Ziti is controlling access to services. In order for us to access the echo service, our client application needs an identity, so that we can permit that identity access.
The main thing our client needs to connect to the Ziti network is an identity. One of the primary functions of Ziti is controlling access to services. In order for us to access the echo service, our
client application needs an identity, so that we can permit that identity access.
## What is an Identity?
It's tempting to think of an identity as either a user or a device, but neither of those is entirely correct. A user may have multiple devices, each of which accesses the same service. In general a user will have a separate identity for each device from which they access the service. There are a few reasons for this approach:
It's tempting to think of an identity as either a user or a device, but neither of those is entirely correct. A user may have multiple devices, each of which accesses the same service. In general a
user will have a separate identity for each device from which they access the service. There are a few reasons for this approach:
* By enrolling each device individually we don’t transfer the credentials between devices. Because we generate the credentials each device, they can’t be intercepted.
* If someone compromises one device, we can disable just that identity, rather than everything for a given user.
* Traffic becomes attributable to a given device, which can be useful in a number of ways, including identifying misbehaving applications.
* Traffic becomes attributable to a given device, which can be useful in a number of ways, including identifying misbehaving applications.
If a user belongs to multiple Ziti networks, they will likely have multiple identities per device. In general, multiple identities on the same device for the same user will not cause any conflicts, unlike trying to run multiple VPNs concurrently. Even when using a Ziti tunnelers, each tunneler can host multiple identities concurrently and there will only be problems if multiple services try to claim the same DNS name or IP.
If a user belongs to multiple Ziti networks, they will likely have multiple identities per device. In general, multiple identities on the same device for the same user will not cause any conflicts,
unlike trying to run multiple VPNs concurrently. Even when using a Ziti tunnelers, each tunneler can host multiple identities concurrently and there will only be problems if multiple services try to
claim the same DNS name or IP.
Creating the Identity
When creating an identity you can specify the identity type as being one of user, service or device. These types are currently just descriptive, and do not affect how Ziti uses the identities. Let’s say you’re running your own software on your laptop. Since you are the company founder, we’ll name the identity founder-laptop. We're also going to assign the identity a role attribute of management. We can use this later when setting up policies.
When creating an identity you can specify the identity type as being one of user, service or device. These types are currently just descriptive, and do not affect how Ziti uses the identities. Let’s
say you’re running your own software on your laptop. Since you are the company founder, we’ll name the identity founder-laptop. We're also going to assign the identity a role attribute of management.
We can use this later when setting up policies.
```action:ziti
ziti edge create identity user founder-laptop -o founder-laptop.jwt --role-attributes management
```
We have now created a new identity of type user with name founder-laptop. When Ziti created the identity, a one-time-token was also generated, which we’ve stored in founder-client.jwt. We’ll use this token to enroll our identity and create the configuration file for our client application.
We have now created a new identity of type user with name founder-laptop. When Ziti created the identity, a one-time-token was also generated, which we’ve stored in founder-client.jwt. We’ll use this
token to enroll our identity and create the configuration file for our client application.
Let’s take a look at our new identity:
@@ -186,9 +209,11 @@ Let’s take a look at our new identity:
ziti edge list identities 'name="founder-laptop"'
```
In addition to the id, name and type we can see that identities, like services and edge routers, also have role-attributes. In the next section we'll be configuring service access, and we’ll see how role attributes come into play.
In addition to the id, name and type we can see that identities, like services and edge routers, also have role-attributes. In the next section we'll be configuring service access, and we’ll see how
role attributes come into play.
Before we can use our new identity, we need to enroll it. Enrolling the identity uses up the one-time-token and generates the configuration, keys and certificates that a client needs to use a Ziti network.
Before we can use our new identity, we need to enroll it. Enrolling the identity uses up the one-time-token and generates the configuration, keys and certificates that a client needs to use a Ziti
network.
```action:ziti
ziti edge enroll -j founder-laptop.jwt -o founder-laptop.json
@@ -196,28 +221,33 @@ ziti edge enroll -j founder-laptop.jwt -o founder-laptop.json
The resulting json file has the address of the Ziti controller, as well as the keys and certificates it needs to establish its identity and communicate securely with that controller.
As you saw, the usual flow for enrolling an application in a ziti network has two steps. However, unlike in our approach here, we don’t generally rely on the Ziti CLI to enroll applications and generate a config file. A more conventional flow would be:
As you saw, the usual flow for enrolling an application in a ziti network has two steps. However, unlike in our approach here, we don’t generally rely on the Ziti CLI to enroll applications and
generate a config file. A more conventional flow would be:
1. Create an identity for the application, which includes generating a JWT
1. The application imports JWT, enrolls in the application and stores the configuration in its own format.
1. Two ways that applications can import JWTs are by reading a file or reading a QR code
The reason enrollment is broken into two steps is because we only want the keys and certificates to exist on their final destination. We may transmit the JWT, but once enrollment has completed the JWT cannot be re-used. If someone later steals the JWT, they won’t be able to enroll, as the JWT will no longer be valid. If some intercepts the JWT and uses it to enroll before the intended recipient does, the intended recipient’s enrollment will fail. This lets us know that something is wrong, we can disable the identity, and the intrusion will have been quickly detected.
The reason enrollment is broken into two steps is because we only want the keys and certificates to exist on their final destination. We may transmit the JWT, but once enrollment has completed the JWT
cannot be re-used. If someone later steals the JWT, they won’t be able to enroll, as the JWT will no longer be valid. If some intercepts the JWT and uses it to enroll before the intended recipient
does, the intended recipient’s enrollment will fail. This lets us know that something is wrong, we can disable the identity, and the intrusion will have been quickly detected.
<!---action:pause-->
## Trying the Ziti Client
Now that we’re enrolled, let’s try to use our echo service.
```action:ziti failOk=true
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
Hopefully it comes as no surprise that the echo service wasn’t found, given that we haven’t granted our identity any access yet.
# Policy Configuration
The Ziti CLI comes with a tool called policy-advisor to help you figure out if you have correctly configured your policies. Let’s try it out. It can be run either from a service or identity-centric perspective. This following command will check if the founder-laptop identity can access the echo service.
The Ziti CLI comes with a tool called policy-advisor to help you figure out if you have correctly configured your policies. Let’s try it out. It can be run either from a service or identity-centric
perspective. This following command will check if the founder-laptop identity can access the echo service.
```action:ziti
ziti edge policy-advisor identities -q founder-laptop echo
@@ -240,7 +270,8 @@ First we need to grant access to use the service via a service policy. There are
* Dial - allow using a service
* Bind - allow hosting a service
For now, we just need a dial policy. Later, when we try hosting the echo service with an SDK embedded application, we’ll need a bind policy as well. We're going to explicitly add our service and identity to this policy. The service we'll reference by name. The identity we'll include by role attribute.
For now, we just need a dial policy. Later, when we try hosting the echo service with an SDK embedded application, we’ll need a bind policy as well. We're going to explicitly add our service and
identity to this policy. The service we'll reference by name. The identity we'll include by role attribute.
For a deep dive into policies, see [here](https://docs.openziti.io/docs/learn/core-concepts/security/authorization/policies/overview/).
@@ -263,7 +294,7 @@ ziti edge policy-advisor identities -q founder-laptop echo
If we try to run the client again, it still won’t work, but we should see a different error:
```action:ziti failOk=true
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
This error indicates that we have access to the service, but not to any edge routers.
@@ -272,13 +303,14 @@ This error indicates that we have access to the service, but not to any edge rou
# Edge Router Policy Setup
Now we need to give our client access to one or more edge routers. Edge routers are how client traffic enters a Ziti network. We need to be able to limit which identities can access specific edge routers. Certain edge routers may be dedicated to specific regions, users or services.
Now we need to give our client access to one or more edge routers. Edge routers are how client traffic enters a Ziti network. We need to be able to limit which identities can access specific edge
routers. Certain edge routers may be dedicated to specific regions, users or services.
```action:ziti templatize=true
ziti edge create edge-router-policy echo-clients --edge-router-roles '@${edgeRouterName}' --identity-roles '#management'
```
Taking a look, we should see now see our new edge router policy in place.
Taking a look, we should see now see our new edge router policy in place.
```action:ziti
ziti edge list edge-router-policies 'name="echo-clients"'
@@ -295,23 +327,25 @@ We should only have one error left, letting us know that the service doesn’t h
If we run the client again, we’ll see the same error:
```action:ziti failOk=true
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
This is because the edge routers that can be used when establishing a session is the set of edge routers that the identity and service have in common.
This is because the edge routers that can be used when establishing a session is the set of edge routers that the identity and service have in common.
Looking at an example:
1. We have an identity which has access to edge routers A, B, C
1. We have an identity which has access to edge routers A, B, C
2. We have a service which can be accessed via edge routers C, D, E
3. That identity can only access the service via edge router C, since that's the only one they have in common
Even though our identity now has access to our edge router, our service does not.
Even though our identity now has access to our edge router, our service does not.
<!---action:pause-->
# Service Edge Router Policies
In the same way that we can assign edge routers to users, we can also assign them to services. You may wish to do this to conform with local regulations or to give services exclusive access to certain edge routers to meet SLAs.
In the same way that we can assign edge routers to users, we can also assign them to services. You may wish to do this to conform with local regulations or to give services exclusive access to certain
edge routers to meet SLAs.
Since we don’t have any special requirements right now, let’s let the echo service use all edge routers. There’s a special role attribute of #all which will match all entities of a given type.
@@ -328,7 +362,7 @@ ziti edge policy-advisor identities -q founder-laptop echo
We should now finally be able to run the client and get some validation.
```action:ziti colorStdOut=false
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
We have our first successful connection through Ziti! **\o/**
@@ -350,7 +384,7 @@ Stop the plain echo server
We’ve stopped the echo server. If we now run the client, we’ll see an error saying that dialing the service fails.
```action:ziti colorStdOut=false failOk=true
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
We’re going to also remove the terminator, since that now points to an address where nothing is running.
@@ -362,7 +396,7 @@ ziti edge delete terminators where 'service.name="echo"'
If we now run the client, we’ll see an error saying that the service has no terminators.
```action:ziti colorStdOut=false failOk=true
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
## Hosting Identity
@@ -381,14 +415,14 @@ ziti edge enroll -j echo-server.jwt -o echo-server.json
## Ziti Server Code
If you look at the server code, viewable [here](../ziti_echo_server.go), you should notice very few changes from the plain echo server. The actual request processing code is unchanged.
If you look at the server code, viewable [here](../ziti_echo_server.go), you should notice very few changes from the plain echo server. The actual request processing code is unchanged.
<!---action:show src=ziti_echo_server.go highlight=go-->
Let’s try running it and see what happens.
```action:ziti colorStdOut=false failOk=true
ziti edge tutorial ziti-echo-server --identity echo-server.json
ziti demo ziti-echo-server --identity echo-server.json
```
Since we haven’t given this identity access to the server, it fails.
@@ -403,7 +437,7 @@ ziti edge policy-advisor identities -q echo-server echo
We should only see two errors.
* The identity does not have access to the service
* The identity does not have access to the service
* The identity does not have access to any edge routers
We already granted the echo service to all edge routers, so that is no longer an issue.
@@ -426,7 +460,8 @@ Running the policy advisor again, we should be down to one error:
ziti edge policy-advisor identities -q echo-server echo
```
Finally, we create an edge router policy for the hosting identity. In this case, it has the same servers as the client side, but generally client side and hosting side identities will use different sets of edge routers.
Finally, we create an edge router policy for the hosting identity. In this case, it has the same servers as the client side, but generally client side and hosting side identities will use different
sets of edge routers.
```action:ziti templatize=true
ziti edge create edge-router-policy echo-servers --edge-router-roles '@${edgeRouterName}' --identity-roles '#echo-server'
@@ -441,36 +476,39 @@ ziti edge policy-advisor identities -q echo-server echo
Let’s give it a try now and see what happens:
```action:run-ziti-echo-server
ziti edge tutorial ziti-echo-server
ziti demo ziti-echo-server
```
Our client should work correctly. Hang on, you may be saying… won’t it fail with a ‘no terminators’ error? After all, we haven’t created a new terminator yet. Well, let’s take a look at our terminators:
Our client should work correctly. Hang on, you may be saying… won’t it fail with a ‘no terminators’ error? After all, we haven’t created a new terminator yet. Well, let’s take a look at our
terminators:
```action:ziti failOk=true
ziti edge list terminators 'service.name="echo"'
```
There’s a terminator present, which looks quite different from the one we created manually. This terminator was created dynamically when the ziti-echo-server application bound the service. Client connections for echo will now get made over the existing network connection that the server application has with the edge router. When you stop the server application, the terminator will be removed.
There’s a terminator present, which looks quite different from the one we created manually. This terminator was created dynamically when the ziti-echo-server application bound the service. Client
connections for echo will now get made over the existing network connection that the server application has with the edge router. When you stop the server application, the terminator will be removed.
This has some interesting benefits. For example, this can make horizontal scale easier to accomplish. When you spin up new instances of the server application, they can connect, dynamically create a terminator and start receiving a portion of the service traffic. When you stop an application, or it dies, the connection goes away, and the terminator is automatically removed. New connections won’t try to connect that application server anymore.
This has some interesting benefits. For example, this can make horizontal scale easier to accomplish. When you spin up new instances of the server application, they can connect, dynamically create a
terminator and start receiving a portion of the service traffic. When you stop an application, or it dies, the connection goes away, and the terminator is automatically removed. New connections won’t
try to connect that application server anymore.
Hosting configuration and topologies is a big topic. For now, let’s try out our client with our single server instance running:
```action:ziti colorStdOut=false
ziti edge tutorial ziti-echo-client --identity founder-laptop.json trees are tall
ziti demo ziti-echo-client --identity founder-laptop.json trees are tall
```
Success, we now have a Ziti SDK-embedded client, communicating with a Ziti SDK-embedded server.
Success, we now have a Ziti SDK-embedded client, communicating with a Ziti SDK-embedded server.
Thanks for taking the time to learn about Ziti services, identities and policies!
Hopefully you’ve gotten a better idea of:
* How to create and manage services and identities
* How to create and manage services and identities
* How terminators connect the Ziti fabric with application servers
* How to manage client access with identities and service policies
* How edge routers can be assigned across identities with edge router policies
* How edge routers can be assigned across services with service edge router polices
See the [Documentation Hub](https://openziti.github.io/) for more resources.
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"context"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"github.com/openziti/ziti/ziti/cmd/common"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"fmt"
@@ -14,7 +14,7 @@
limitations under the License.
*/
package tutorial
package demo
import (
"github.com/openziti/ziti/ziti/cmd/common"
-68
View File
@@ -1,68 +0,0 @@
/*
Copyright NetFoundry Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tutorial
import (
"github.com/openziti/ziti/ziti/cmd/common"
"github.com/openziti/ziti/ziti/cmd/edge"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/spf13/cobra"
"time"
)
func init() {
edge.ExtraEdgeCommands = append(edge.ExtraEdgeCommands, NewTutorialCmd)
}
func NewTutorialCmd(p common.OptionsProvider) *cobra.Command {
cmd := &cobra.Command{
Use: "tutorial",
Short: "Interactive tutorials for learning about Ziti",
Run: func(cmd *cobra.Command, args []string) {
err := cmd.Help()
cmdhelper.CheckErr(err)
},
}
cmd.AddCommand(newFirstServiceTutorialCmd(p))
cmd.AddCommand(newPlainEchoServerCmd(p))
cmd.AddCommand(newPlainEchoClientCmd(p))
cmd.AddCommand(newZitiEchoClientCmd(p))
cmd.AddCommand(newZitiEchoServerCmd(p))
return cmd
}
type TutorialOptions struct {
ControllerUrl string
Username string
Password string
NewlinePause time.Duration
AssumeDefault bool
}
func (self *TutorialOptions) GetControllerUrl() string {
return self.ControllerUrl
}
func (self *TutorialOptions) GetUsername() string {
return self.Username
}
func (self *TutorialOptions) GetPassword() string {
return self.Password
}
+1 -1
View File
@@ -11,7 +11,7 @@ require (
github.com/michaelquigley/pfxlog v0.6.10
github.com/openziti/channel/v2 v2.0.81
github.com/openziti/edge v0.24.348
github.com/openziti/fablab v0.5.0
github.com/openziti/fablab v0.5.1
github.com/openziti/fabric v0.23.39
github.com/openziti/foundation/v2 v2.0.26
github.com/openziti/identity v1.0.57
+2 -2
View File
@@ -647,8 +647,8 @@ github.com/openziti/edge v0.24.348 h1:m0zh1n5OBj7Tjemu9XfxdYhbKvo6HdGQMHfC/Zledb
github.com/openziti/edge v0.24.348/go.mod h1:wcoBVKqW99/CBg7LjzbHT3dJ8JMlRZelPhbjNcjwMr0=
github.com/openziti/edge-api v0.25.29 h1:DbZ0GKpch9ik+XnC0qoP1dOg1AmgUEeWH4VIyOIehrQ=
github.com/openziti/edge-api v0.25.29/go.mod h1:mqYquh1RYvHjV/M9MGO4Ng0Xq9ixAH8o8cT5kw5XCWY=
github.com/openziti/fablab v0.5.0 h1:+CMVE08hS62UR3tIfEvMb3XcWwzD1np//cpHHTboVW8=
github.com/openziti/fablab v0.5.0/go.mod h1:VLvs0AAuKAFqy8jhGvs+FgszYEbB456duPOBfRj4peU=
github.com/openziti/fablab v0.5.1 h1:dc3c88vBuJ4OlIyv49T+xUy/GNtvQ0lsEUPE9VH2MCE=
github.com/openziti/fablab v0.5.1/go.mod h1:VLvs0AAuKAFqy8jhGvs+FgszYEbB456duPOBfRj4peU=
github.com/openziti/fabric v0.23.39 h1:t6npkfBsPr+8GvF9X/rTLHxGsce5FTa4NoA80MInxYc=
github.com/openziti/fabric v0.23.39/go.mod h1:px2zUzQrgObmv6sdXgGJ028Wr45aGcgpFvfIP/qgDFo=
github.com/openziti/foundation/v2 v2.0.26 h1:RISGM97aIFnnEkxrcVsO6fnGg9W4ByydSnqWAVkJAqY=
+2 -1
View File
@@ -40,10 +40,11 @@ func TestSdkEcho(t *testing.T) {
ssh := lib.NewSshConfigFactory(c.GetHost())
remoteConfigFile := "/home/ubuntu/fablab/cfg/" + c.Id + ".json"
echoClientCmd := fmt.Sprintf(`echo "%s" | /home/%s/fablab/bin/ziti learn demo zcat --identity %s ziti:echo 2>&1`,
echoClientCmd := fmt.Sprintf(`echo "%s" | /home/%s/fablab/bin/ziti demo zcat --identity %s ziti:echo 2>&1`,
string(data), ssh.User(), remoteConfigFile)
output, err := lib.RemoteExec(ssh, echoClientCmd)
t.Logf("test output:\n%s", output)
req.NoError(err)
//trim the newline ssh added
output = strings.TrimRight(output, "\n")