diff --git a/doc/release-notes-0.10.md b/doc/release-notes-0.10.md deleted file mode 100644 index 3d324e33e..000000000 --- a/doc/release-notes-0.10.md +++ /dev/null @@ -1,16 +0,0 @@ -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.9.x to version 0.10.x - -# Theme -Ziti 0.10 includes a single change: - - * Edge API input validation processing was changed to operate on the supplied JSON instead of target objects - - -# Edge API Validation - -Before this version, the Edge API allowed some fields to be omitted from requests. This behavior was due to the fact -that the API was validating the object that resulted from the JSON. This would cause some fields that were not supplied -to default to an acceptable nil/null/empty value. - -Some APIs call may now fail with validation errors expecting fields to be defined for POST (create) and PUT (update) -operations. PATCH (partial update) should not be affected. \ No newline at end of file diff --git a/doc/release-notes-0.11.md b/doc/release-notes-0.11.md deleted file mode 100644 index 40d2eb071..000000000 --- a/doc/release-notes-0.11.md +++ /dev/null @@ -1,12 +0,0 @@ -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.10.x to version 0.11.x - -# Theme -Ziti 0.11 includes the following: - - * Ziti connections from Ziti SDK client to services hosted by SDK are encrypted end-to-end (no API changes) - - -# End-to-end Encryption - -Client and Hosting SDK instances setup end-to-end channels using secure key exchange and [AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption) streams. -Read more about on https://netfoundry.github.io/ziti-doc (_coming soon_) \ No newline at end of file diff --git a/doc/release-notes-0.12.md b/doc/release-notes-0.12.md deleted file mode 100644 index c645b71f6..000000000 --- a/doc/release-notes-0.12.md +++ /dev/null @@ -1,156 +0,0 @@ -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.11.x to version 0.12.x - -# Theme -Ziti 0.12 includes the following: - - * Terminators have been extracted from services - * Terminators define where a service terminates. Previously each service had exactly one terminator. Now services can have 0 to N terminators. - * List APIs now support inline paging - * Association APIs now support filtering, paging and querying - * The bolt datastore creates a backup of the datastore file before attempting a schema/data migration - * Fabric and edge code are now much more closely aligned at the persistence and model layers - * Some deprecated endpoints are now being removed - -# Terminators -See https://github.com/netfoundry/ziti-fabric/wiki/Pluggable-Service-Terminators for a discussion of what serivice terminators are, the motivation for extracting them from services and the design for how they will work. - -This release includes the following: - - * Terminators extracted from service as separate entities - * When SDK applications bind and unbind, the controller now dynamically adds/removes terminators as appropriate - -This release does not yet include a terminator strategy API. Strategies can be specified per service, but if a service has multiple terminators the first one will be used. The terminator strategy API along with some implementations will be added in a follow-up release. This release also does not include strategy inputs on terminators as discussed in the above design document. If strategy inputs end up being useful, they may be added in the furure. - -## Terminator related API changes - -There is a new terminators endpoint: - - * Endpoint: /terminators - * Supported operations - * Detail: GET /terminators/ - * List: GET /terminators/ - * Create: POST /terminators - * Update All Fields: PUT /terminators/ - * Update Selective Fields: PATCH /terminators/ - * Delete: DELETE /terminators/ - * Properties - * Terminators support the standard properties (id, createdAt, updatedAt, tags) - * service - type: uuid, must be a valid service id - * router - type: uuid, must be a valid router id - * binding - type: string. Optional, defaults to "transport". The xgress binding on the selected router to use - * address - type: string. The address that will be dialed using the xgress component on the selected router - -The service endpoint has changes as well: - - * Endpoint: /services - * New operations - * Query related endpoints: GET /services//terminators?filter= - * The following properties have been removed - * egressRouter - * endpointAddress - * The following property has been added - * terminatorStrategy - type: string, optional. The terminator strategy to use. Currently unused. - -The fabric service definition has also changed (visible from ziti-fabric). - - * The following properties have been removed - * `binding` - * `egressRouter` - * `endpointAddress` - * The following property has been added - * `terminatorStrategy` - -The ziti and ziti-fabric CLIs have been updated with new terminator related functionality, so that terminators can be viewed, created and deleted from both. - -# Filtering/Sorting/Paging Changes -List operations on entities previously allowed the following parameters: - - * `filter` - * `sort` - * `limit` - * `offset` - -These are all still supported, but now sort, limit and offset can also be included in the filter. If parameters are specified both in the filter and in an explicit query parameter, the filter takes precedence. - -When listing entities from the ziti CLI, filters can be included as an optional argument. - -For example: - - $ ziti edge controller list services - id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} - id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} - id: 9480e39d-0664-4482-b230-5da2c17b225b name: iperf terminator strategy: role attributes: {} - id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} - id: dc0446f0-7eaa-465f-80b5-c88f0a6b59cc name: grpc-ping terminator strategy: role attributes: ["fortio","fortio-server"] - id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} - - $ ziti edge controller list services 'name contains "s"' - id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} - id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} - id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} - id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} - - $ ziti edge controller list services 'name contains "s" sort by name' - id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} - id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} - id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} - id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} - - $ ziti edge controller list services 'name contains "s" sort by name skip 1 limit 2' - id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} - id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} - -Association lists now also support filtering, sorting and paging. Association GET operations only support the filter parameter. - - - $ ziti edge controller list service terminators ssh - Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh - id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 - id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 - - $ ziti edge controller list service terminators ssh "true sort by address" - Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh - id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 - id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 - - $ ziti edge controller list service terminators ssh "true sort by address desc" - Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh - id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 - id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 - -# Bolt Datastore Migrations -The fabric now supports migrating schema/data from one version to another. The fabric and edge share a common framework for migration. The migration framework now also automatically backs up the bolt data file before migration data. The backup file will have the same name as the original bolt file but with a timestamp appended to it. - -Example: - - Original file: /tmp/ziti-bolt.db - Backup file: /tmp/ziti-bolt.db-20200316-134725 - -The fabric and edge schemas do not yet get migrated in the same transaction. This will be addressed in a follow-up release. - -# Fabric and Edge Alignment -The fabric and edge persistence and model layers are now using the same foundational plumbing. This will allow for a common API layer in a follow-up release. - -As part of this consolidation effort, fabric entities now share the same set of common properties as edge entities, namely: - - * `id` - * `createdAt` - * `updatedAt` - * `tags` - -Previously the only common property was `id`. - -# Deprecated Endpoints -The `/gateways` (replaced by `/edge-routers`) and `network-sessions` (replaced by `/sessions`) endpoints, which were previously deprecated, have now been removed. - -# Miscellaneous - -There is a new `ziti edge controller version` command which shows information about the version of the controller being connected to: - -Example: - - $ ziti edge controller version - Version : v0.9.0 - GIT revision: ea556fc18740 - Build Date : 2020-02-11 16:09:08 - Runtime : go1.13 diff --git a/doc/release-notes-0.6.md b/doc/release-notes-0.6.md deleted file mode 100644 index b575c0dc9..000000000 --- a/doc/release-notes-0.6.md +++ /dev/null @@ -1,165 +0,0 @@ - - -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.5.x to version 0.6.x - -# Theme -Ziti 0.6.0 move the back-end persistence model of Ziti Edge and Ziti Fabric into the same repository based on Bbolt (an in memory data store that is backed by a memory mapped file). The changes remove the requirement for PostgresSQL. - -# UPDB Enrollment JWTs -Enrollments that are for UPDB (username password database) are now consistent with all other enrollment and use JWTs for processing. Prior to this a naked URL was provided. - -## What This Breaks -Any UPDB enrollment processing that relied upon the URL for the enrollment. - - - -Ziti 0.5.x UPDB enrolling entity - -``` -{ - "meta": {}, - "data": { - "id": "612843ae-6ac8-48ac-a737-bfc2d28ab9ea", - "createdAt": "2019-11-21T17:23:00.316631Z", - "updatedAt": "2019-11-21T17:23:00.316631Z", - "_links": { - "self": { - "href": "./identities/612843ae-6ac8-48ac-a737-bfc2d28ab9ea" - } - }, - "tags": {}, - "name": "updb--5badbdc5-e8dd-4877-82df-c06aea7f1197", - "type": { - "id": "577104f2-1e3a-4947-a927-7383baefbc9a", - "name": "User" - }, - "isDefaultAdmin": false, - "isAdmin": false, - "authenticators": {}, - "enrollment": { - "updb": { - "username": "asdf", - "url": "https://demo.ziti.netfoundry.io:1080/enroll?method=updb&token=911e6562-0c83-11ea-a81a-000d3a1b4b17&username=asdf" - } - }, - "permissions": [] - } -} -``` - -Ziti 0.6.x UPDB enrolling entity (note the changes in the enrollment.updb object): - -``` -{ - "meta": {}, - "data": { - "id": "39f11c10-0693-41ed-9bec-8011e2721562", - "createdAt": "2019-11-21T17:28:18.2855234Z", - "updatedAt": "2019-11-21T17:28:18.2855234Z", - "_links": { - "self": { - "href": "./identities/39f11c10-0693-41ed-9bec-8011e2721562" - } - }, - "tags": {}, - "name": "updb--b55f5372-3993-40f5-b534-126e0dd2f1be", - "type": { - "entity": "identity-types", - "id": "577104f2-1e3a-4947-a927-7383baefbc9a", - "name": "User", - "_links": { - "self": { - "href": "./identity-types/577104f2-1e3a-4947-a927-7383baefbc9a" - } - } - }, - "isDefaultAdmin": false, - "isAdmin": false, - "authenticators": {}, - "enrollment": { - "updb": { - "expiresAt": "2019-11-21T17:33:18.2855234Z", - "issuedAt": "2019-11-21T17:28:18.2855234Z", - "jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbSI6InVwZGIiLCJleHAiOjE1NzQzNTc1OTgsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjEyODAiLCJqdGkiOiJiYzBlY2NlOC05ZGY0LTQzZDYtYTVhMC0wMjI1MzY2YmM4M2EiLCJzdWIiOiIzOWYxMWMxMC0wNjkzLTQxZWQtOWJlYy04MDExZTI3MjE1NjIifQ.PUcnACCdwqfWRGRzF8lG6xDTgHKAwKV6eTw8tHFuNBXaUNbqExBwUQEW0-cCHsV-nLEyhxyjhXmVCkIDgz-ukKfS0xStiDrJQbiq8m0auodkArmJSsYzElXkKdv37FHu0t-CGoXptdLyuo9eCnzzmci3ev18zMR5HjYMCQEclELV6OEICNr_0EwhAGJa1yX6ODYrLMZ3SdEd6fj-ZGX7j9owTs6iEsqCB_TORfnGGg6lEINE5GlYsyp7JUxolS6H4lPeN5h2mxk2_OkJY8GX3ydv75LsIZ-jjL3xC5XncCESrefgDabib1fudJ4038D0EzqTcOREPAqmjWhnDhTulQ", - "token": "bc0ecce8-9df4-43d6-a5a0-0225366bc83a" - } - }, - "permissions": [] - } -} -``` - - - -## What To Do -Use the new JWT format to: - -verify the signature of the JWT to match the iss URL's TSL presented certificates -construct the enrollment url from the JWTs properties in the following format: - -``` - + "/enroll?token=" + -``` - -# Multiple Invalid Value Error Handling -Errors where there is the potential to report about multiple invalid field values for a given field used to report as a separate error for each value. Now there will be one error, but the values field will hold the invalid values. - -## Old Format -``` -{ - "error": { - "args": { - "urlVars": { - "id": "097018b6-108e-42b3-869b-deb9e1814594" - } - }, - "cause": { - "errors": [ - { - "message": "entity not found for id [06ecf930-3a9f-4a6c-98b5-8f0be1bde9e2]", - "field": "ids[0]", - "value": "06ecf930-3a9f-4a6c-98b5-8f0be1bde9e2" - } - ] - }, - "causeMessage": "There were multiple field errors: the value '06ecf930-3a9f-4a6c-9...' for 'ids[0]' is invalid: entity not found for id [06ecf930-3a9f-4a6c-98b5-8f0be1bde9e2]", - "code": "INVALID_FIELD", - "message": "The field contains an invalid value", - "requestId": "48ea4bce-f233-410e-a062-5dbceee20223" - }, - "meta": { - "apiEnrolmentVersion": "0.0.1", - "apiVersion": "0.0.1" - } -} -``` - -## New Format -``` -{ - "error": { - "args": { - "urlVars": { - "id": "5b15c442-5590-4c58-8bc7-0da788e0cfcf" - } - }, - "cause": { - "message": "clusters(s) not found", - "field": "clusters", - "value": [ - "68f8739f-cf52-4d51-9553-dfe7cf9c6a03" - ] - }, - "causeMessage": "the value '[68f8739f-cf52-4d51-9553-dfe7cf9c6a03]' for 'clusters' is invalid: clusters(s) not found", - "code": "INVALID_FIELD", - "message": "The field contains an invalid value", - "requestId": "ab6553e8-e9b1-408c-9fed-11cc627cfd84" - }, - "meta": { - "apiEnrolmentVersion": "0.0.1", - "apiVersion": "0.0.1" - } -} -``` - - \ No newline at end of file diff --git a/doc/release-notes-0.7.md b/doc/release-notes-0.7.md deleted file mode 100644 index e1982cc2f..000000000 --- a/doc/release-notes-0.7.md +++ /dev/null @@ -1,99 +0,0 @@ - - -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.6.x to version 0.7.x - -# Theme - * Ziti 0.7.0 replaces clusters with role attribute based policies - * Ziti 0.7.0 takes steps towards consistent terminology for sessions - -# Edge Router Policy -In 0.6.0 access to edge routers was controlled by clusters and services. - - * Every edge router was assigned to a cluster - * Services belonged to 1 or more clusters - * Dial/bind request would results would include a list of edge routers which were - * in clusters linked to the dialed/bound service and - * were online when the request was made - -Release 0.7.0 replaces this model with something new. It has the following goals: - - * Allow grouping edge routers and other entities dynamically using role attributes rather than hard-coded lists - * Allow restricting access to edge router by identity in addition to by service - -It includes the following new concepts: - - * Role attributes - * Role attributes are just a set of strings associated to a model entity - * The semantics of the role attributes are determined by the system administrator - * Ex: an edge router might have the role attributes `["us-east", "new-york", "omnicorp"]` - * These tags might indicate that this edge router is located on the east coast of the USA, specifically in New York and should be dedicated to use by a customer named OmniCorp - * Currently role attributes are supported on edge routers and identities - * Roles - * Roles specify a set of entities - * Roles may include role attributes as well as entity ids - * A role will match all entities which either: - * Have **_all_** role attributes in the role OR - * Have an ID which is listed explicitly - * Role attributes are prefixed with `@`. Role elements not prefixed with `@` are assumed to be ids - * There is a special role attribute `@all` which will match all entities - * A role may have only role attributes or only ids or may have both - -## Role Example - * Edge router with id 1 has role attributes `["us-east", "New York City"]` - * Edge router with id 2 has role attributes `["us-east", "Albany"]` - * Edge router with id 3 has role attributes `["us-west", "Los Angeles"]` - * An edge router role of `["@us-east", "@New York City", "3"]` would evaluate as follows - * Edge router 1 would match because it has all listed role attributes - * Edge router 2 would not match, because it doesn't have all listed role attributes - * Edge router 3 would match because its ID is listed explicitly - -## Model Changes -### Role Attributes -Edge routers and identities now have roleAttributes fields. Edge routers no longer have an associated cluster. - -### Edge Router Policies -0.7.0 introduces a new model construct, the Edge Router Policy. This entity allows restricting which edge routers identities are allowed to use. An edge router policy has three attributes: - - * Name - * Identity Roles - * Edge Router Roles - -An identity can be a member of multiple policies and will have access to the union of all edge routers linked to from those policies. - -There is a new `/edge-router-policies` endpoint which can be used for creating/updating/deleting/querying edge router policies. Edge router policies PUT/POST/PATCH all take the following properties: - - * name - * edgeRouterRoles - * identityRoles - * tags - -### Service Edge Router Roles -Services now have a new edgeRouterRoles field. If set, this specifies which edge routers may be used for a service. This replaces the old cluster functionality. - -### Edge Router Access -When a service is dialed or bound, which edge routers will be returned? - - * If the service edgeRouterRoles are NOT set, then it will be the set of edge routers to which the dialing/binding identity has access - * If the service edgeRouterRoles ARE set, then it will be the intersection of the edge routers to which the service has access and the set of edge routers to which the identity has access - -### Cluster Removal and Migration -The `/clusters` endpoint has been removed. The bbolt schema version has been bumped to 2. If starting a fresh controller no action will be taken. However, if coming from an existing 0.6 or earlier bbolt database, the following will be done: - - 1. An edge router policy will be created with `@all` for both identityRoles and edgeRouterRoles, allowing access to all edge routers from all identities. This will allow the current identities to continue using the system. Otherwise, no identities would be able to connect to any edge routers. - 2. Each edge router will get a role attribute of `cluster-` for the cluster it belonged to - 3. If a service belongs to 1 or more clusters it will get a role attribute corresponding to the first cluster. Any edge routers assigned to additional clusters will be added to edge router roles field by ID. - 1. Noe: If we were to add additional role clusters for the other clusts we'd get the intersection, not the union and would end up with access to 0 edge routers - -# Session changes -Terminology related to sessions is being made consistent between the edge and fabric. - -There are two types of sessions: - - 1. Sessions between edge clients the edge controller, which allowed clients to manage controller state as well as dial and bind services - 1. These were referred to as sessions in the edge and have no fabric equivalent - 1. Sessions which establish routing and allow data flow to/from/within the edge and fabric - 1. These were referred to as network sessions in the edge and sessions in the fabric - -Going forward, what was called a session in the edge will now be referred to as an API session. What was called a network session will be now just be called session in both the edge and fabric. - -As a first step, in 0.7.0 API sessions will be available at both the `/sessions` and `/api-sessions` endpoints. Use of the `/sessions` endpoint is deprecated. In later releases the `/sessions` endpoint will be used for sessions instead of API sessions. diff --git a/doc/release-notes-0.8.md b/doc/release-notes-0.8.md deleted file mode 100644 index 81e707134..000000000 --- a/doc/release-notes-0.8.md +++ /dev/null @@ -1,171 +0,0 @@ -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.7.x to version 0.8.x - -# Theme - * Ziti 0.8.0 replaces appwans with role attribute based service policies - * Ziti 0.8.0 consolidates dial and bind permissions into service policies - -# Service Policy -In 0.7.0 and prior access to services was controlled by appwans. - - * Appwans had lists of identities and services - * Identities and services could be associated with 0-n appwans - * Services had explicit lists of identities that could bind the service - * In order to dial a service, the identity had to be an admin or be in at least one appwan with that service - * In order to bind a serivice, the identity had to be able to dial the service and be in the list of identities allowed to bind the service - -Release 0.8.0 replaces this model with something new. It has the following goals: - - * Allow grouping identities and services dynamically using role attributes rather than hard-coded lists - * Consolidate dial and bind permissions into the same model - -The following concepts were introduced in 0.7 for edge router policies. They are now used for service policies as well. - - * Role attributes - * Role attributes are just a set of strings associated to a model entity - * The semantics of the role attributes are determined by the system administrator - * Ex: an edge router might have the role attributes `["us-east", "new-york", "omnicorp"]` - * These tags might indicate that this edge router is located on the east coast of the USA, specifically in New York and should be dedicated to use by a customer named OmniCorp - * Currently role attributes are supported on edge routers and identities - * Roles - * Roles specify a set of entities - * Roles may include role attributes as well as entity ids - * A role will match all entities which either: - * Have **_all_** role attributes in the role OR - * Have an ID which is listed explicitly - * Role attributes are prefixed with `@`. Role elements not prefixed with `@` are assumed to be ids - * There is a special role attribute `@all` which will match all entities - * A role may have only role attributes or only ids or may have both - -## Role Example - * Service with id 1 has role attributes `["sales", "New York City"]` - * Service with id 2 has role attributes `["sales", "Albany"]` - * Service with id 3 has role attributes `["support", "Los Angeles"]` - * A service role of `["@sales", "@New York City", "3"]` would evaluate as follows - * Service 1 would match because it has all listed role attributes - * Service 2 would not match, because it doesn't have all listed role attributes - * Service 3 would match because its ID is listed explicitly - -## Model Changes -### Session Names - 1. api sessions had two endpoints in 0.7, `/api-sessions` and `/sessions` which was deprecated. `/sessions` is now no longer valid for api sessions - 2. sessions used the `/network-sessions` endpoint. In this release, `/network-sessions` has been deprecated and `/sessions` should be used instead. - 3. `/current-session` is now `/current-api-session` - -### Session Format - 1. When creating a session, the returned JSON has the same base format as when listing sessions, so it now includes the service and api-session information. The only difference is that the session token is also returned from session create, but not when listing sessions. - 1. The gateways attribute of session has been renamed to edgeRouters. - -### Role Attributes -Services now have a roleAttributes field. Identities already had a roleAttributes field, for used with edge router policies. - -### Service Policies -0.8.0 introduces a new model construct, the Service Policy. This entity allows restricting which services identities are allowed to dial or bind. A service policy has four attributes: - - * Name - * Policy Type ("Bind" or "Dial") - * Identity Roles - * Service Roles - -An identity can be a member of multiple policies and will have access to the union of all services linked to from those policies. - -There is a new `/service-policies` endpoint which can be used for creating/updating/deleting/querying service policies. Service policies PUT/POST/PATCH all take the following properties: - - * name - * type - * valid values are "Bind" and "Dial" - * identityRoles - * serviceRoles - * tags - -There are also new association endpoints allowing the listing of services and identities associated with service policies and vice-versa. - - * /service-policies//services - * /service-policies//identities - * /identities//service-policies - * /services//service-policies - -### Service Access - * An admin may dial or bind any service - * A non-admin identity may dial any service it has access to via service policies of type "Dial" - * A non-admin identity may bind any service it has access to via service policies of type "Bind" - -When listing services, the controller used to provide a hostable flag with each service to indicate if the service could be bound in addition to being dialed. Now, the service will have a permissions block which will indicate if the service may be dialed, bound or both. - -Ex: -```json - { - "meta": {}, - "data": { - "id": "1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba", - "createdAt": "2020-01-04T02:34:00.788444359Z", - "updatedAt": "2020-01-04T02:34:00.788444359Z", - "_links": { - "edge-routers": { - "href": "./services/1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba/edge-routers" - }, - "self": { - "href": "./services/1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba" - }, - "service-policies": { - "href": "./services/1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba/identities" - } - }, - "tags": {}, - "name": "cac9593c-0494-4800-9f70-c258ff28a702", - "dns": { - "hostname": "0bf71754-ed5b-4b2d-9adf-a542f1284275", - "port": 0 - }, - "endpointAddress": "4662d564-3fc3-4f10-b8cd-ee0e3629ad24", - "egressRouter": "aedab92f-2ddf-445a-9194-73d428322a34", - "edgeRouterRoles": null, - "roleAttributes": [ - "2c68789a-fe71-4d25-a483-43e54ee4fd98" - ], - "permissions": [ - "Bind" - ] - } - } -``` - -### Appwan Removal and Migration -The `/app-wans` endpoint has been removed. The bbolt schema version has been bumped to 3. If starting a fresh controller no action will be taken. However, if coming from an existing 0.7 or earlier bbolt database, the following will be done: - - 1. For each existing appwan, a service policy with type "Dial" will be created - 1. The new service policy will have the same name as the appwan it replaces - 1. The new service policy will have the same identities and services as the appwan it replaces - 1. Identities and services will be specified explicitly by ID rather as opposed to by creating new role attributes - -NOTE: Service hosting identities will not be migrated into equivalent Bind service policies, as binds are not yet used in any production scenarios. - -# Go SDK changes -Several types have been renamed to conform to standard nomenclature - - * Session is now ApiSession - * NetworkSession is now Session - * The SessionId field is now ApiSessionId - * The Gateways field is now EdgeRouters - * Gateway is now EdgeRouter - * On the Service type the Hostable flag has been removed and replaced with a Permissions string array - * It may be nil, empty or contain either or both of "Dial" and "Bind" - * On the Context type - * GetNetworkSession is now GetSession - * GetNetworkHostSession is now GetBindSession - -# ziti command line changes - 1. The `ziti edge controller create/delete gateway` commands have been removed. Use `ziti edge controller create/delete edge-router` instead. - 2. There are new `ziti edge controller create/delete service-policy` commands - -# Ziti Proxy changes -ziti-proxy has been incorporated into the ziti-tunnel command. Where previously one would have run - -``` -ZITI_SDK_CONFIG=./config.json ziti-proxy run -``` - -now one should use - -``` -ziti-tunnel proxy -i ./config.json -``` diff --git a/doc/release-notes-0.9.md b/doc/release-notes-0.9.md deleted file mode 100644 index c2acf4977..000000000 --- a/doc/release-notes-0.9.md +++ /dev/null @@ -1,286 +0,0 @@ -This page discusses the changes that you need to be aware of when migrating your Ziti deployment from version 0.8.x to version 0.9.x - -# Theme -Ziti 0.9 includes the following - - * a generic service configuration facility, useful for configuring service centric edge configuration data - * several changes to policy syntax and semantics - * service edge router policies are now a separate entity, instead of just a field on service - - -# Service Configuration -Configurations are named JSON style objects that can be associated with services. Configurations have a type. -A service can have 0 or 1 configurations of each configuration type associated with it. - -## Configuration types -There is a new endpoint for managing config types. - - * Endpoint: `/config-types` - * Supported operations - * Detail: GET `/config-types/` - * List: GET `/config-types/` - * Create: POST `/config-types` - * Update All Fields: PUT `/config-types/` - * Update Selective Fields: PATCH `/config-types/` - * Delete: DELETE `/config-types/` - * List associated configs GET `/config-types//configs` - * Properties - * Config types support the standard properties (id, createdAt, updatedAt, tags) - * name - type: string, constraints: required, must be unique. If provided must be a valid JSON schema. - * schema - type: object. Optional. - -If a schema is set on a type, that schema will be used to validate config data on configurations of that type. Validation -will happen if a configuration is created or updated. If a config type schema changes, the system does not re-validate -configurations of that type. - -It is generally assumed that if there are backwards incompatible changes being made to a schema that a new config type -will be created and interested applications can support multiple configuration types. - -The ziti CLI supports the following operations on config types: - - * create config-type - * list config-types - * list config-type configs - * delete config-type - -## Configurations -There is a new endpoint for managing configurations - - * Endpoint: `/configs` - * Supported operations - * Detail: GET `/configs/` - * List: GET `/configs/` - * Create: POST `/configs/` - * Update All Fields: PUT `/configs/` - * Update Selective Fields: PATCH `/configs/` - * Delete: DELETE `/config-types/` - * Properties - * Configs support the standard properties (id, createdAt, updatedAt, tags) - * name - type: string, constraints: unique - * type - type: string. May be a config type id or config type name - * data - type: JSON object - * Support values are strings, numbers, booleans and nested objects/maps - -The ziti CLI supports the following operations on configs: - - * create config - * update config - * list configs - * delete config - -```shell script -$ ziti edge controller create config ssh ziti-tunneler-client.v1 '{ "hostname" : "ssh.mycompany.com", "port" : 22 }' -83a1e815-04bc-4c91-8d88-1de8c943545f - -$ ziti edge controller list configs -id: 83a1e815-04bc-4c91-8d88-1de8c943545f -name: ssh -type: f2dd2df0-9c04-4b84-a91e-71437ac229f1 -data: { - "hostname": "ssh.mycompany.com", - "port": 22 - } - -$ ziti edge controller update config ssh -d '{ "hostname" : "ssh.mycompany.com", "port" : 2022 }' -Found configs with id 83a1e815-04bc-4c91-8d88-1de8c943545f for name ssh - -$ ziti edge controller list configs -id: 83a1e815-04bc-4c91-8d88-1de8c943545f -name: ssh -type: f2dd2df0-9c04-4b84-a91e-71437ac229f1 -data: { - "hostname": "ssh.mycompany.com", - "port": 2022 - } - -$ ziti edge controller delete config ssh -Found configs with id 83a1e815-04bc-4c91-8d88-1de8c943545f for name ssh - -$ ziti edge controller list configs -$ -``` - -## Service Configuration -The DNS block, which included hostname and port, has been removed from service definitions. When creating or updating -services, you can submit a `configs` array, which may include config ids or names (or a mix of the two). Configs are -not required. - -**NOTE**: Only one config of a given type may be associated with a service. - -Configurations associated with a service may be listed as entities using: - - * List associated configs GET `/services//configs` - -### Retrieving service configuration -When authenticating, a user may now indicate which config types should be included when listing services. -The authentication POST may include a body. If the body has a content-type of application/json, it will -be parsed as a map. The controller will looking for a key at the top level of the map called `configTypes`, -which should be an array of config type ids or names (or mix of the two). - -Example authentication POST body: -```json -{ - "configTypes" : ["ziti-tunneler-client.v1", "ziti-tunneler-client.v2"] -} -``` -When retrieving services, the config data for for those configuration types that were requested will be embedded in -the service definition. For example, if the user has requested (by name) the config types "ziti-tunneler-client.v1" and -"ziti-tunneler-server.v1" and the `ssh` service has configurations of both of those kinds associated, a listing which -includes that service might look as follows: - -```json -{ - "meta": { - "filterableFields": [ - "id", - "createdAt", - "updatedAt", - "name", - "dnsHostname", - "dnsPort" - ], - "pagination": { - "limit": 10, - "offset": 0, - "totalCount": 1 - } - }, - "data": [ - { - "id": "2e79d56a-e37a-4f32-9769-f934976843d9", - "createdAt": "2020-01-23T20:08:58.634275277Z", - "updatedAt": "2020-01-23T20:08:58.634275277Z", - "_links": { - "edge-routers": { - "href": "./services/2e79d56a-e37a-4f32-9769-f934976843d9/edge-routers" - }, - "self": { - "href": "./services/2e79d56a-e37a-4f32-9769-f934976843d9" - }, - "service-policies": { - "href": "./services/2e79d56a-e37a-4f32-9769-f934976843d9/identities" - } - }, - "tags": {}, - "name": "ssh", - "endpointAddress": "tcp:localhost:22", - "egressRouter": "cf5d76cb-3fff-4dce-8376-60b2bfb505a6", - "edgeRouterRoles": null, - "roleAttributes": null, - "permissions": [ - "Dial" - ], - "config": { - "ziti-tunneler-client.v1": { - "hostname": "ssh.mycompany.com", - "port": 22 - }, - "ziti-tunneler-server.v1": { - "protocol" : "tcp", - "hostname": "ssh.mycompany.com", - "port": 22 - } - } - } - ] -} -``` - -## Identity Service Configuration -Configuration for a service can also be specified for a given identity. If a configuration is specified for a service, -it will replace any configuration of that type on that service. - - * Endpoint /identities//identities?filter= + * Query related services: GET /edge-routers//services?filter= + + * Endpoint: /identities + * New operations + * Query related edge routers: GET /identities//edge-routers?filter= + * Query related services: GET /identities//services?filter= + + * Endpoint: /services + * New operations + * Query related identities: GET /services//identities?filter= + * Query related edge routers: GET /services//edge-routers?filter= + +## Filtering Entity Lists by Roles +When building UIs it may be useful to list entities which have role attributes by role filters, to see what policy changes may look like. + + * Endpoint: /edge-routers + * Query: GET /edge-routers now supports two new query paramters + * roleFilter. May be specified more than one. Should be an id or role specifier (ex: @38683097-2412-4335-b056-ae8747314dd3 or #sales) + * roleSemantic. Optional. Defaults to AllOf if not specified. Indicates which semantic to use when evaluating role matches + + * Endpoint: /identities + * Query: GET /identities now supports two new query paramters + * roleFilter. May be specified more than one. Should be an id or role specifier (ex: @38683097-2412-4335-b056-ae8747314dd3 or #sales) + * roleSemantic. Optional. Defaults to AllOf if not specified. Indicates which semantic to use when evaluating role matches + + * Endpoint: /services + * Query: GET /services now supports two new query paramters + * roleFilter. May be specified more than one. Should be an id or role specifier (ex: @38683097-2412-4335-b056-ae8747314dd3 or #sales) + * roleSemantic. Optional. Defaults to AllOf if not specified. Indicates which semantic to use when evaluating role matches + +Note that a roleFilter should have one role specifier (like `@some-id` or `#sales`). If you wish to specify multiple, provide multiple role filters. + + /edge-routers?roleFilter=#sales&roleFilter=#us + +These are also supported from the CLI when listing edge routers, identities and services using the --role-filters and --role-semantic flags. + +Example: + + $ ec list services + id: 2a724ae7-8b8f-4688-90df-34951bce6720 name: grpc-ping terminator strategy: role attributes: ["fortio","fortio-server"] + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: 38683097-2412-4335-b056-ae8747314dd3 name: quux terminator strategy: role attributes: ["blop","sales","three"] + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: 9480e39d-0664-4482-b230-5da2c17b225b name: iperf terminator strategy: role attributes: {} + id: a949cf80-b11b-4cce-bbb7-d2e4767878a6 name: baz terminator strategy: role attributes: ["development","sales","support"] + id: ad95ec7d-6c05-42b6-b278-2a98a7e502df name: bar terminator strategy: role attributes: ["four","three","two"] + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + id: e9673c77-7463-4517-a642-641ef35855cf name: foo terminator strategy: role attributes: ["one","three","two"] + + $ ec list services --role-filters '#three' + id: 38683097-2412-4335-b056-ae8747314dd3 name: quux terminator strategy: role attributes: ["blop","sales","three"] + id: ad95ec7d-6c05-42b6-b278-2a98a7e502df name: bar terminator strategy: role attributes: ["four","three","two"] + id: e9673c77-7463-4517-a642-641ef35855cf name: foo terminator strategy: role attributes: ["one","three","two"] + + $ ec list services --role-filters '#three','#two' + id: ad95ec7d-6c05-42b6-b278-2a98a7e502df name: bar terminator strategy: role attributes: ["four","three","two"] + id: e9673c77-7463-4517-a642-641ef35855cf name: foo terminator strategy: role attributes: ["one","three","two"] + + $ ec list services --role-filters '#three','#sales' --role-semantic AnyOf + id: 38683097-2412-4335-b056-ae8747314dd3 name: quux terminator strategy: role attributes: ["blop","sales","three"] + id: a949cf80-b11b-4cce-bbb7-d2e4767878a6 name: baz terminator strategy: role attributes: ["development","sales","support"] + id: ad95ec7d-6c05-42b6-b278-2a98a7e502df name: bar terminator strategy: role attributes: ["four","three","two"] + id: e9673c77-7463-4517-a642-641ef35855cf name: foo terminator strategy: role attributes: ["one","three","two"] + + $ ec list services --role-filters '#three''#sales','@4e33859b-070d-42b1-8b40-4adf973f680c' --role-semantic AnyOf + id: 38683097-2412-4335-b056-ae8747314dd3 name: quux terminator strategy: role attributes: ["blop","sales","three"] + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: a949cf80-b11b-4cce-bbb7-d2e4767878a6 name: baz terminator strategy: role attributes: ["development","sales","support"] + id: ad95ec7d-6c05-42b6-b278-2a98a7e502df name: bar terminator strategy: role attributes: ["four","three","two"] + id: e9673c77-7463-4517-a642-641ef35855cf name: foo terminator strategy: role attributes: ["one","three","two"] + +## Policy Advisor +This adds a new operation to the /identities endpoint + + * Endpoint: /identities + * New operations + * Query related identities: GET /identities//policy-advice/ + +This will return the following information about the identity and service: + + * If the identity can dial the service + * If the identity can bind the service + * How many edge routers the identity has access to + * How many edge routers the service can be accessed through + * Which edge routers the identity and service have in common (if this is none, then the service can't be accessed by the identity) + * Which of the common edge routers are on-line + +Example result: + + { + "meta": {}, + "data": { + "identityId": "700347c8-ca3a-4438-9060-68f7255ee4f8", + "identity": { + "entity": "identities", + "id": "700347c8-ca3a-4438-9060-68f7255ee4f8", + "name": "ssh-host", + "_links": { + "self": { + "href": "./identities/700347c8-ca3a-4438-9060-68f7255ee4f8" + } + } + }, + "serviceId": "8fa27a3e-ffb1-4bd1-befa-fcd38a6c26b3", + "service": { + "entity": "services", + "id": "8fa27a3e-ffb1-4bd1-befa-fcd38a6c26b3", + "name": "ssh", + "_links": { + "self": { + "href": "./services/8fa27a3e-ffb1-4bd1-befa-fcd38a6c26b3" + } + } + }, + "isBindAllowed": true, + "isDialAllowed": false, + "identityRouterCount": 2, + "serviceRouterCount": 2, + "commonRouters": [ + { + "entity": "edge-routers", + "id": "43d220d8-860e-4d80-a25c-97322a7326b4", + "name": "us-west-1", + "_links": { + "self": { + "href": "./edge-routers/43d220d8-860e-4d80-a25c-97322a7326b4" + } + }, + "isOnline": false + }, + { + "entity": "edge-routers", + "id": "8c118857-c12e-430d-9109-c31f535933f6", + "name": "us-east-1", + "_links": { + "self": { + "href": "./edge-routers/8c118857-c12e-430d-9109-c31f535933f6" + } + }, + "isOnline": true + } + ] + } + } + +The CLI has also been updated with a new policy-advisor common. + +Examples: + + # Inspect all identities for policy issues + ziti edge controller policy-advisor identities + + # Inspect just the jsmith-laptop identity for policy issues with all services that the identity can access + ziti edge controller policy-advisor identities jsmith-laptop + + # Inspect the jsmith-laptop identity for issues related to the ssh service + ziti edge controller policy-advisor identities jsmith-laptop ssh + + # Inspect all services for policy issues + ziti edge controller policy-advisor services + + # Inspect just the ssh service for policy issues for all identities the service can access + ziti edge controller policy-advisor services ssh + + # Inspect the ssh service for issues related to the jsmith-laptop identity + ziti edge controller policy-advisor identities ssh jsmith-laptop + +Some example output of the CLI: + + $ ec policy-advisor identities -q + ERROR: mlapin-laptop (1) -> ssh-backup (0) Common Routers: (0/0) Dial: Y Bind: N + - Service has no edge routers assigned. Adjust service edge router policies. + + ERROR: mlapin-laptop (1) -> ssh (2) Common Routers: (0/0) Dial: Y Bind: N + - Identity and services have no edge routers in common. Adjust edge router policies and/or service edge router policies. + + ERROR: ndaniels-laptop (1) -> ssh-backup (0) Common Routers: (0/0) Dial: Y Bind: N + - Service has no edge routers assigned. Adjust service edge router policies. + + ERROR: ndaniels-laptop (1) -> ssh (2) Common Routers: (0/1) Dial: Y Bind: N + - Common edge routers are all off-line. Bring routers back on-line or adjust edge router policies and/or service edge router policies to increase common router pool. + + ERROR: Default Admin + - Identity does not have access to any services. Adjust service policies. + + ERROR: jsmith-laptop (2) -> ssh-backup (0) Common Routers: (0/0) Dial: Y Bind: N + - Service has no edge routers assigned. Adjust service edge router policies. + + OKAY : jsmith-laptop (2) -> ssh (2) Common Routers: (1/2) Dial: Y Bind: N + + ERROR: ssh-host (2) -> ssh-backup (0) Common Routers: (0/0) Dial: N Bind: Y + - Service has no edge routers assigned. Adjust service edge router policies. + + OKAY : ssh-host (2) -> ssh (2) Common Routers: (1/2) Dial: N Bind: Y + + ERROR: aortega-laptop + - Identity does not have access to any services. Adjust service policies. + + ERROR: djones-laptop (0) -> ssh-backup (0) Common Routers: (0/0) Dial: Y Bind: N + - Identity has no edge routers assigned. Adjust edge router policies. + - Service has no edge routers assigned. Adjust service edge router policies. + + ERROR: djones-laptop (0) -> ssh (2) Common Routers: (0/0) Dial: Y Bind: N + - Identity has no edge routers assigned. Adjust edge router policies. + + $ ec policy-advisor identities aortega-laptop ssh-backup -q + Found identities with id 70567104-d4bd-45f1-8179-bd1e6ab8751f for name aortega-laptop + Found services with id 46e94977-0efc-4e7d-b9ae-cc8df1c95fc1 for name ssh-backup + ERROR: aortega-laptop (0) -> ssh-backup (0) Common Routers: (0/0) Dial: N Bind: N + - No access to service. Adjust service policies. + - Identity has no edge routers assigned. Adjust edge router policies. + - Service has no edge routers assigned. Adjust service edge router policies. + +## CA Auto Enrollment Identity Attributes + +Identities that are enrolled via a CA can now inherit a static list of identity role attributes. The normal create, +update, patch requests supported by the CA entities now allow the role attributes to be specified. CA identity role +attribute changes do no propagate to identities that have completed enrollment. + +This feature allows a simple degree of automation for identities that are auto-provisioning through a third party CA. + + * `identityRoles` added to `/ca` endpoints for normal CRUD operations + * `identityRoles` from a CA entity are point-in-time copies + +## New APIs to list and manage Transit Routers + +The endpoint`/transit-routers` has been added to create and manage Transit Routers. Transit Routers do not handle incoming Ziti +Edge SDK connections. + + * Endpoint: /transit-routers + * Supported operations + * Detail: GET /transit-routers/ + * List: GET /transit-routers/ + * Create: POST /transit-routers + * Update All Fields: PUT /transit-routers/ + * Update Selective Fields: PATCH /transit-routers/ + * Delete: DELETE /transit-routers/ + * Properties + * Transit Routers support the standard properties (id, createdAt, updatedAt, tags) + * name - Type string - a friendly Edge name for the transit router + * fingerprint - Type string - a hex string fingerprint of the transit router's public certificate (post enrollment) + * isVerified - Type bool - true if the router has completed enrollment + * isOnline - Type bool - true if the router is currently connected to the controller + * enrollmentToken - Type string - the enrollment token that would be used during enrollment (nil post enrollment) + * enrollmentJwt - Type string - an enrollment JWT suitable for use with "ziti-router enroll" (nil post enrollment) + * enrollmentCreatedAt - Type date-time - the date and time the enrollment was created (nil post enrollment) + * enrollmentExpiresAt - Type date-time - the date and time the enrollment expires at (matches JWT expiration time, nil post enrollment) + +Example list output: +```json +{ + "meta": { + "filterableFields": [ + "id", + "createdAt", + "updatedAt", + "name" + ], + "pagination": { + "limit": 10, + "offset": 0, + "totalCount": 2 + } + }, + "data": [ + { + "id": "002", + "createdAt": "2020-03-30T00:55:38.1701084Z", + "updatedAt": "2020-03-30T00:55:38.1701084Z", + "_links": { + "self": { + "href": "./transit-routers/002" + } + }, + "tags": {}, + "name": "", + "fingerprint": "07e011481921b4734df82c52ae2b3113617cdd18", + "isVerified": true, + "isOnline": false, + "enrollmentToken": null, + "enrollmentJwt": null, + "enrollmentCreatedAt": null, + "enrollmentExpiresAt": null + }, + { + "id": "99f4109b-cd6d-40e3-9a62-bee24d7eccd6", + "createdAt": "2020-03-30T17:48:17.2949059Z", + "updatedAt": "2020-03-30T17:48:17.2949059Z", + "_links": { + "self": { + "href": "./transit-routers/99f4109b-cd6d-40e3-9a62-bee24d7eccd6" + } + }, + "tags": {}, + "name": "", + "fingerprint": "25d1048f3c7bc4a5956ce7316e2ca70999c0e27d", + "isVerified": true, + "isOnline": false, + "enrollmentToken": null, + "enrollmentJwt": null, + "enrollmentCreatedAt": null, + "enrollmentExpiresAt": null + } + ] +} +``` +## Transit Routers now support enrolment via `ziti-router enroll` + +Transit Routers now enroll using the same command: `ziti-router enroll -j `. During the enrollment process, +the CSR properties used will be taken from `edge.csr`. If `edge.csr` does not exist `csr` will be utilized. If both are +missing an error will occur. + +Example router configuration: + +```yaml +v: 2 + +identity: + cert: testdata/transit-router/transit-router-client.cert.pem + server_cert: testdata/transit-router/transit-router-server.cert.pem + key: testdata/transit-router/transit-router.key.pem + ca: testdata/transit-router/transit-router-ca-chain.cert.pem + +ctrl: + endpoint: tls:127.0.0.1:6262 + +csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + sans: + dns: + - "localhost" + - "test-network" + - "test-network.localhost" + - "ziti-dev-ingress01" + email: + - "admin@example.com" + ip: + - "127.0.0.1" + uri: + - "ziti://ziti-dev-gateway01/made/up/example" + +dialers: + - binding: udp + - binding: transport + +listeners: + - binding: transport + address: tls:0.0.0.0:7099 +``` + +## Embedded Swagger/OpenAPI 2.0 endpoint + +The endpoint`/specs` has been added to retrieve API specifications from the Ziti Controller. The specifications +are specific to the version of the controller deployed. + +The main endpoint to retrieve the Swagger/Open API 2.0 specification is: `/specs/swagger/spec` + + * Endpoint: /specs + * Supported operations + * Detail: GET /specs/ + * Get Spec: GET /specs//spec + * List: GET /specs/ + * Properties + * Transit Routers support the standard properties (id, createdAt, updatedAt, tags) + * name - Type string - the and intent of the spec + + +## APIs now only accept ID, not ID or Name + 1. Some APIs related to configurations accepted config names or ids. These now only accept name. + 1. Policies would accept entity references with names as well as ids. So you could use `@ssh`, for example when referencing the ssh service. These now also only accept ID + +In general allowing both values adds complexity to the server side code. Consuming code, such as user interfaces or the ziti cli, can do the name to id translation just as easily. + +## Fabric Enhancements +### Xlink Framework + +The new Xlink framework **requires** that the router configuration file is updated to `v: 3`. + +The `link` section of the router configuration is now structured like this: + +``` +link: + listeners: + - binding: transport + bind: tls:127.0.0.1:6002 + advertise: tls:127.0.0.1:6002 + options: + outQueueSize: 16 + dialers: + - binding: transport +``` + +The `link/listeners/bind` address replaces the old `link/listener` address, and the `link/listeners/advertise` address replaces the old `link/advertise` address. + +**The router configuration MUST be updated to include `link/dialers` section with a `transport` binding (as in the above example) to include support for outbound link dialing.** + +Subsequent releases will include support for multiple Xlink listeners and dialers. 0.13 supports only a single listener and dialer to be configured. + +### Xgress MTU + +The Xgress listeners and dialers now support an `mtu` option in their `options` stanza: + +``` +listeners: + # basic ssh proxy + - binding: proxy + address: tcp:0.0.0.0:1122 + service: ssh + options: + mtu: 768 + +dialers: + - binding: transport + options: + mtu: 512 +``` +This MTU controls the maximum size of the `Payload` packet sent across the data plane of the overlay. + +# Release 0.12 +## Theme +Ziti 0.12 includes the following: + + * Terminators have been extracted from services + * Terminators define where a service terminates. Previously each service had exactly one terminator. Now services can have 0 to N terminators. + * List APIs now support inline paging + * Association APIs now support filtering, paging and querying + * The bolt datastore creates a backup of the datastore file before attempting a schema/data migration + * Fabric and edge code are now much more closely aligned at the persistence and model layers + * Some deprecated endpoints are now being removed + +## Terminators +See https://github.com/netfoundry/ziti-fabric/wiki/Pluggable-Service-Terminators for a discussion of what serivice terminators are, the motivation for extracting them from services and the design for how they will work. + +This release includes the following: + + * Terminators extracted from service as separate entities + * When SDK applications bind and unbind, the controller now dynamically adds/removes terminators as appropriate + +This release does not yet include a terminator strategy API. Strategies can be specified per service, but if a service has multiple terminators the first one will be used. The terminator strategy API along with some implementations will be added in a follow-up release. This release also does not include strategy inputs on terminators as discussed in the above design document. If strategy inputs end up being useful, they may be added in the furure. + +### Terminator related API changes + +There is a new terminators endpoint: + + * Endpoint: /terminators + * Supported operations + * Detail: GET /terminators/ + * List: GET /terminators/ + * Create: POST /terminators + * Update All Fields: PUT /terminators/ + * Update Selective Fields: PATCH /terminators/ + * Delete: DELETE /terminators/ + * Properties + * Terminators support the standard properties (id, createdAt, updatedAt, tags) + * service - type: uuid, must be a valid service id + * router - type: uuid, must be a valid router id + * binding - type: string. Optional, defaults to "transport". The xgress binding on the selected router to use + * address - type: string. The address that will be dialed using the xgress component on the selected router + +The service endpoint has changes as well: + + * Endpoint: /services + * New operations + * Query related endpoints: GET /services//terminators?filter= + * The following properties have been removed + * egressRouter + * endpointAddress + * The following property has been added + * terminatorStrategy - type: string, optional. The terminator strategy to use. Currently unused. + +The fabric service definition has also changed (visible from ziti-fabric). + + * The following properties have been removed + * `binding` + * `egressRouter` + * `endpointAddress` + * The following property has been added + * `terminatorStrategy` + +The ziti and ziti-fabric CLIs have been updated with new terminator related functionality, so that terminators can be viewed, created and deleted from both. + +## Filtering/Sorting/Paging Changes +List operations on entities previously allowed the following parameters: + + * `filter` + * `sort` + * `limit` + * `offset` + +These are all still supported, but now sort, limit and offset can also be included in the filter. If parameters are specified both in the filter and in an explicit query parameter, the filter takes precedence. + +When listing entities from the ziti CLI, filters can be included as an optional argument. + +For example: + + $ ziti edge controller list services + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: 9480e39d-0664-4482-b230-5da2c17b225b name: iperf terminator strategy: role attributes: {} + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + id: dc0446f0-7eaa-465f-80b5-c88f0a6b59cc name: grpc-ping terminator strategy: role attributes: ["fortio","fortio-server"] + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + + $ ziti edge controller list services 'name contains "s"' + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + + $ ziti edge controller list services 'name contains "s" sort by name' + id: 37f1e34c-af06-442f-8e62-032916912bc6 name: grpc-ping-standalone terminator strategy: role attributes: {} + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + id: cd1ae16e-5015-49ad-9864-3ca0f5814091 name: ssh terminator strategy: role attributes: {} + + $ ziti edge controller list services 'name contains "s" sort by name skip 1 limit 2' + id: dcc9922a-c681-41bf-8079-be2163509702 name: mattermost terminator strategy: role attributes: {} + id: 4e33859b-070d-42b1-8b40-4adf973f680c name: simple terminator strategy: role attributes: {} + +Association lists now also support filtering, sorting and paging. Association GET operations only support the filter parameter. + + + $ ziti edge controller list service terminators ssh + Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh + id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 + id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 + + $ ziti edge controller list service terminators ssh "true sort by address" + Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh + id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 + id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 + + $ ziti edge controller list service terminators ssh "true sort by address desc" + Found services with id cd1ae16e-5015-49ad-9864-3ca0f5814091 for name ssh + id: 41f4fd01-0bd7-4987-93b3-3b2217b00a22 serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:22 + id: a5213300-9c5f-4b0e-a790-1ed460964d7c serviceId: cd1ae16e-5015-49ad-9864-3ca0f5814091 routerId: 888cfde1-5786-4ba8-aa75-9f97804cb7bb binding: transport address: tcp:localhost:2022 + +## Bolt Datastore Migrations +The fabric now supports migrating schema/data from one version to another. The fabric and edge share a common framework for migration. The migration framework now also automatically backs up the bolt data file before migration data. The backup file will have the same name as the original bolt file but with a timestamp appended to it. + +Example: + + Original file: /tmp/ziti-bolt.db + Backup file: /tmp/ziti-bolt.db-20200316-134725 + +The fabric and edge schemas do not yet get migrated in the same transaction. This will be addressed in a follow-up release. + +## Fabric and Edge Alignment +The fabric and edge persistence and model layers are now using the same foundational plumbing. This will allow for a common API layer in a follow-up release. + +As part of this consolidation effort, fabric entities now share the same set of common properties as edge entities, namely: + + * `id` + * `createdAt` + * `updatedAt` + * `tags` + +Previously the only common property was `id`. + +## Deprecated Endpoints +The `/gateways` (replaced by `/edge-routers`) and `network-sessions` (replaced by `/sessions`) endpoints, which were previously deprecated, have now been removed. + +## Miscellaneous + +There is a new `ziti edge controller version` command which shows information about the version of the controller being connected to: + +Example: + + $ ziti edge controller version + Version : v0.9.0 + GIT revision: ea556fc18740 + Build Date : 2020-02-11 16:09:08 + Runtime : go1.13 + +# Release 0.11 +##Theme +Ziti 0.11 includes the following: + + * Ziti connections from Ziti SDK client to services hosted by SDK are encrypted end-to-end (no API changes) + + +## End-to-end Encryption + +Client and Hosting SDK instances setup end-to-end channels using secure key exchange and [AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption) streams. +Read more about on https://netfoundry.github.io/ziti-doc (_coming soon_) + +# Releaes 0.10 +## Theme +Ziti 0.10 includes a single change: + + * Edge API input validation processing was changed to operate on the supplied JSON instead of target objects + + +## Edge API Validation + +Before this version, the Edge API allowed some fields to be omitted from requests. This behavior was due to the fact +that the API was validating the object that resulted from the JSON. This would cause some fields that were not supplied +to default to an acceptable nil/null/empty value. + +Some APIs call may now fail with validation errors expecting fields to be defined for POST (create) and PUT (update) +operations. PATCH (partial update) should not be affected. + +# Release 0.9 +## Theme +Ziti 0.9 includes the following + + * a generic service configuration facility, useful for configuring service centric edge configuration data + * several changes to policy syntax and semantics + * service edge router policies are now a separate entity, instead of just a field on service + + +## Service Configuration +Configurations are named JSON style objects that can be associated with services. Configurations have a type. +A service can have 0 or 1 configurations of each configuration type associated with it. + +### Configuration types +There is a new endpoint for managing config types. + + * Endpoint: `/config-types` + * Supported operations + * Detail: GET `/config-types/` + * List: GET `/config-types/` + * Create: POST `/config-types` + * Update All Fields: PUT `/config-types/` + * Update Selective Fields: PATCH `/config-types/` + * Delete: DELETE `/config-types/` + * List associated configs GET `/config-types//configs` + * Properties + * Config types support the standard properties (id, createdAt, updatedAt, tags) + * name - type: string, constraints: required, must be unique. If provided must be a valid JSON schema. + * schema - type: object. Optional. + +If a schema is set on a type, that schema will be used to validate config data on configurations of that type. Validation +will happen if a configuration is created or updated. If a config type schema changes, the system does not re-validate +configurations of that type. + +It is generally assumed that if there are backwards incompatible changes being made to a schema that a new config type +will be created and interested applications can support multiple configuration types. + +The ziti CLI supports the following operations on config types: + + * create config-type + * list config-types + * list config-type configs + * delete config-type + +### Configurations +There is a new endpoint for managing configurations + + * Endpoint: `/configs` + * Supported operations + * Detail: GET `/configs/` + * List: GET `/configs/` + * Create: POST `/configs/` + * Update All Fields: PUT `/configs/` + * Update Selective Fields: PATCH `/configs/` + * Delete: DELETE `/config-types/` + * Properties + * Configs support the standard properties (id, createdAt, updatedAt, tags) + * name - type: string, constraints: unique + * type - type: string. May be a config type id or config type name + * data - type: JSON object + * Support values are strings, numbers, booleans and nested objects/maps + +The ziti CLI supports the following operations on configs: + + * create config + * update config + * list configs + * delete config + +```shell script +$ ziti edge controller create config ssh ziti-tunneler-client.v1 '{ "hostname" : "ssh.mycompany.com", "port" : 22 }' +83a1e815-04bc-4c91-8d88-1de8c943545f + +$ ziti edge controller list configs +id: 83a1e815-04bc-4c91-8d88-1de8c943545f +name: ssh +type: f2dd2df0-9c04-4b84-a91e-71437ac229f1 +data: { + "hostname": "ssh.mycompany.com", + "port": 22 + } + +$ ziti edge controller update config ssh -d '{ "hostname" : "ssh.mycompany.com", "port" : 2022 }' +Found configs with id 83a1e815-04bc-4c91-8d88-1de8c943545f for name ssh + +$ ziti edge controller list configs +id: 83a1e815-04bc-4c91-8d88-1de8c943545f +name: ssh +type: f2dd2df0-9c04-4b84-a91e-71437ac229f1 +data: { + "hostname": "ssh.mycompany.com", + "port": 2022 + } + +$ ziti edge controller delete config ssh +Found configs with id 83a1e815-04bc-4c91-8d88-1de8c943545f for name ssh + +$ ziti edge controller list configs +$ +``` + +### Service Configuration +The DNS block, which included hostname and port, has been removed from service definitions. When creating or updating +services, you can submit a `configs` array, which may include config ids or names (or a mix of the two). Configs are +not required. + +**NOTE**: Only one config of a given type may be associated with a service. + +Configurations associated with a service may be listed as entities using: + + * List associated configs GET `/services//configs` + +#### Retrieving service configuration +When authenticating, a user may now indicate which config types should be included when listing services. +The authentication POST may include a body. If the body has a content-type of application/json, it will +be parsed as a map. The controller will looking for a key at the top level of the map called `configTypes`, +which should be an array of config type ids or names (or mix of the two). + +Example authentication POST body: +```json +{ + "configTypes" : ["ziti-tunneler-client.v1", "ziti-tunneler-client.v2"] +} +``` +When retrieving services, the config data for for those configuration types that were requested will be embedded in +the service definition. For example, if the user has requested (by name) the config types "ziti-tunneler-client.v1" and +"ziti-tunneler-server.v1" and the `ssh` service has configurations of both of those kinds associated, a listing which +includes that service might look as follows: + +```json +{ + "meta": { + "filterableFields": [ + "id", + "createdAt", + "updatedAt", + "name", + "dnsHostname", + "dnsPort" + ], + "pagination": { + "limit": 10, + "offset": 0, + "totalCount": 1 + } + }, + "data": [ + { + "id": "2e79d56a-e37a-4f32-9769-f934976843d9", + "createdAt": "2020-01-23T20:08:58.634275277Z", + "updatedAt": "2020-01-23T20:08:58.634275277Z", + "_links": { + "edge-routers": { + "href": "./services/2e79d56a-e37a-4f32-9769-f934976843d9/edge-routers" + }, + "self": { + "href": "./services/2e79d56a-e37a-4f32-9769-f934976843d9" + }, + "service-policies": { + "href": "./services/2e79d56a-e37a-4f32-9769-f934976843d9/identities" + } + }, + "tags": {}, + "name": "ssh", + "endpointAddress": "tcp:localhost:22", + "egressRouter": "cf5d76cb-3fff-4dce-8376-60b2bfb505a6", + "edgeRouterRoles": null, + "roleAttributes": null, + "permissions": [ + "Dial" + ], + "config": { + "ziti-tunneler-client.v1": { + "hostname": "ssh.mycompany.com", + "port": 22 + }, + "ziti-tunneler-server.v1": { + "protocol" : "tcp", + "hostname": "ssh.mycompany.com", + "port": 22 + } + } + } + ] +} +``` + +### Identity Service Configuration +Configuration for a service can also be specified for a given identity. If a configuration is specified for a service, +it will replace any configuration of that type on that service. + + * Endpoint /identities//services + * /service-policies//identities + * /identities//service-policies + * /services//service-policies + +#### Service Access + * An admin may dial or bind any service + * A non-admin identity may dial any service it has access to via service policies of type "Dial" + * A non-admin identity may bind any service it has access to via service policies of type "Bind" + +When listing services, the controller used to provide a hostable flag with each service to indicate if the service could be bound in addition to being dialed. Now, the service will have a permissions block which will indicate if the service may be dialed, bound or both. + +Ex: +```json + { + "meta": {}, + "data": { + "id": "1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba", + "createdAt": "2020-01-04T02:34:00.788444359Z", + "updatedAt": "2020-01-04T02:34:00.788444359Z", + "_links": { + "edge-routers": { + "href": "./services/1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba/edge-routers" + }, + "self": { + "href": "./services/1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba" + }, + "service-policies": { + "href": "./services/1012d4d7-3ab3-4722-8fa3-ae9f4da3c8ba/identities" + } + }, + "tags": {}, + "name": "cac9593c-0494-4800-9f70-c258ff28a702", + "dns": { + "hostname": "0bf71754-ed5b-4b2d-9adf-a542f1284275", + "port": 0 + }, + "endpointAddress": "4662d564-3fc3-4f10-b8cd-ee0e3629ad24", + "egressRouter": "aedab92f-2ddf-445a-9194-73d428322a34", + "edgeRouterRoles": null, + "roleAttributes": [ + "2c68789a-fe71-4d25-a483-43e54ee4fd98" + ], + "permissions": [ + "Bind" + ] + } + } +``` + +#### Appwan Removal and Migration +The `/app-wans` endpoint has been removed. The bbolt schema version has been bumped to 3. If starting a fresh controller no action will be taken. However, if coming from an existing 0.7 or earlier bbolt database, the following will be done: + + 1. For each existing appwan, a service policy with type "Dial" will be created + 1. The new service policy will have the same name as the appwan it replaces + 1. The new service policy will have the same identities and services as the appwan it replaces + 1. Identities and services will be specified explicitly by ID rather as opposed to by creating new role attributes + +NOTE: Service hosting identities will not be migrated into equivalent Bind service policies, as binds are not yet used in any production scenarios. + +## Go SDK changes +Several types have been renamed to conform to standard nomenclature + + * Session is now ApiSession + * NetworkSession is now Session + * The SessionId field is now ApiSessionId + * The Gateways field is now EdgeRouters + * Gateway is now EdgeRouter + * On the Service type the Hostable flag has been removed and replaced with a Permissions string array + * It may be nil, empty or contain either or both of "Dial" and "Bind" + * On the Context type + * GetNetworkSession is now GetSession + * GetNetworkHostSession is now GetBindSession + +## ziti command line changes + 1. The `ziti edge controller create/delete gateway` commands have been removed. Use `ziti edge controller create/delete edge-router` instead. + 2. There are new `ziti edge controller create/delete service-policy` commands + +## Ziti Proxy changes +ziti-proxy has been incorporated into the ziti-tunnel command. Where previously one would have run + +``` +ZITI_SDK_CONFIG=./config.json ziti-proxy run +``` + +now one should use + +``` +ziti-tunnel proxy -i ./config.json +``` + +# Release 0.7 +## Theme + * Ziti 0.7.0 replaces clusters with role attribute based policies + * Ziti 0.7.0 takes steps towards consistent terminology for sessions + +## Edge Router Policy +In 0.6.0 access to edge routers was controlled by clusters and services. + + * Every edge router was assigned to a cluster + * Services belonged to 1 or more clusters + * Dial/bind request would results would include a list of edge routers which were + * in clusters linked to the dialed/bound service and + * were online when the request was made + +Release 0.7.0 replaces this model with something new. It has the following goals: + + * Allow grouping edge routers and other entities dynamically using role attributes rather than hard-coded lists + * Allow restricting access to edge router by identity in addition to by service + +It includes the following new concepts: + + * Role attributes + * Role attributes are just a set of strings associated to a model entity + * The semantics of the role attributes are determined by the system administrator + * Ex: an edge router might have the role attributes `["us-east", "new-york", "omnicorp"]` + * These tags might indicate that this edge router is located on the east coast of the USA, specifically in New York and should be dedicated to use by a customer named OmniCorp + * Currently role attributes are supported on edge routers and identities + * Roles + * Roles specify a set of entities + * Roles may include role attributes as well as entity ids + * A role will match all entities which either: + * Have **_all_** role attributes in the role OR + * Have an ID which is listed explicitly + * Role attributes are prefixed with `@`. Role elements not prefixed with `@` are assumed to be ids + * There is a special role attribute `@all` which will match all entities + * A role may have only role attributes or only ids or may have both + +### Role Example + * Edge router with id 1 has role attributes `["us-east", "New York City"]` + * Edge router with id 2 has role attributes `["us-east", "Albany"]` + * Edge router with id 3 has role attributes `["us-west", "Los Angeles"]` + * An edge router role of `["@us-east", "@New York City", "3"]` would evaluate as follows + * Edge router 1 would match because it has all listed role attributes + * Edge router 2 would not match, because it doesn't have all listed role attributes + * Edge router 3 would match because its ID is listed explicitly + +### Model Changes +#### Role Attributes +Edge routers and identities now have roleAttributes fields. Edge routers no longer have an associated cluster. + +#### Edge Router Policies +0.7.0 introduces a new model construct, the Edge Router Policy. This entity allows restricting which edge routers identities are allowed to use. An edge router policy has three attributes: + + * Name + * Identity Roles + * Edge Router Roles + +An identity can be a member of multiple policies and will have access to the union of all edge routers linked to from those policies. + +There is a new `/edge-router-policies` endpoint which can be used for creating/updating/deleting/querying edge router policies. Edge router policies PUT/POST/PATCH all take the following properties: + + * name + * edgeRouterRoles + * identityRoles + * tags + +#### Service Edge Router Roles +Services now have a new edgeRouterRoles field. If set, this specifies which edge routers may be used for a service. This replaces the old cluster functionality. + +#### Edge Router Access +When a service is dialed or bound, which edge routers will be returned? + + * If the service edgeRouterRoles are NOT set, then it will be the set of edge routers to which the dialing/binding identity has access + * If the service edgeRouterRoles ARE set, then it will be the intersection of the edge routers to which the service has access and the set of edge routers to which the identity has access + +#### Cluster Removal and Migration +The `/clusters` endpoint has been removed. The bbolt schema version has been bumped to 2. If starting a fresh controller no action will be taken. However, if coming from an existing 0.6 or earlier bbolt database, the following will be done: + + 1. An edge router policy will be created with `@all` for both identityRoles and edgeRouterRoles, allowing access to all edge routers from all identities. This will allow the current identities to continue using the system. Otherwise, no identities would be able to connect to any edge routers. + 2. Each edge router will get a role attribute of `cluster-` for the cluster it belonged to + 3. If a service belongs to 1 or more clusters it will get a role attribute corresponding to the first cluster. Any edge routers assigned to additional clusters will be added to edge router roles field by ID. + 1. Noe: If we were to add additional role clusters for the other clusts we'd get the intersection, not the union and would end up with access to 0 edge routers + +## Session changes +Terminology related to sessions is being made consistent between the edge and fabric. + +There are two types of sessions: + + 1. Sessions between edge clients the edge controller, which allowed clients to manage controller state as well as dial and bind services + 1. These were referred to as sessions in the edge and have no fabric equivalent + 1. Sessions which establish routing and allow data flow to/from/within the edge and fabric + 1. These were referred to as network sessions in the edge and sessions in the fabric + +Going forward, what was called a session in the edge will now be referred to as an API session. What was called a network session will be now just be called session in both the edge and fabric. + +As a first step, in 0.7.0 API sessions will be available at both the `/sessions` and `/api-sessions` endpoints. Use of the `/sessions` endpoint is deprecated. In later releases the `/sessions` endpoint will be used for sessions instead of API sessions. + +# Release 0.6 +## Theme +Ziti 0.6.0 moves the back-end persistence model of Ziti Edge and Ziti Fabric into the same repository based on Bbolt (an in memory data store that is backed by a memory mapped file). The changes remove the requirement for PostgresSQL. + +## UPDB Enrollment JWTs +Enrollments that are for UPDB (username password database) are now consistent with all other enrollment and use JWTs for processing. Prior to this a naked URL was provided. + +### What This Breaks +Any UPDB enrollment processing that relied upon the URL for the enrollment. + + + +Ziti 0.5.x UPDB enrolling entity + +``` +{ + "meta": {}, + "data": { + "id": "612843ae-6ac8-48ac-a737-bfc2d28ab9ea", + "createdAt": "2019-11-21T17:23:00.316631Z", + "updatedAt": "2019-11-21T17:23:00.316631Z", + "_links": { + "self": { + "href": "./identities/612843ae-6ac8-48ac-a737-bfc2d28ab9ea" + } + }, + "tags": {}, + "name": "updb--5badbdc5-e8dd-4877-82df-c06aea7f1197", + "type": { + "id": "577104f2-1e3a-4947-a927-7383baefbc9a", + "name": "User" + }, + "isDefaultAdmin": false, + "isAdmin": false, + "authenticators": {}, + "enrollment": { + "updb": { + "username": "asdf", + "url": "https://demo.ziti.netfoundry.io:1080/enroll?method=updb&token=911e6562-0c83-11ea-a81a-000d3a1b4b17&username=asdf" + } + }, + "permissions": [] + } +} +``` + +Ziti 0.6.x UPDB enrolling entity (note the changes in the enrollment.updb object): + +``` +{ + "meta": {}, + "data": { + "id": "39f11c10-0693-41ed-9bec-8011e2721562", + "createdAt": "2019-11-21T17:28:18.2855234Z", + "updatedAt": "2019-11-21T17:28:18.2855234Z", + "_links": { + "self": { + "href": "./identities/39f11c10-0693-41ed-9bec-8011e2721562" + } + }, + "tags": {}, + "name": "updb--b55f5372-3993-40f5-b534-126e0dd2f1be", + "type": { + "entity": "identity-types", + "id": "577104f2-1e3a-4947-a927-7383baefbc9a", + "name": "User", + "_links": { + "self": { + "href": "./identity-types/577104f2-1e3a-4947-a927-7383baefbc9a" + } + } + }, + "isDefaultAdmin": false, + "isAdmin": false, + "authenticators": {}, + "enrollment": { + "updb": { + "expiresAt": "2019-11-21T17:33:18.2855234Z", + "issuedAt": "2019-11-21T17:28:18.2855234Z", + "jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbSI6InVwZGIiLCJleHAiOjE1NzQzNTc1OTgsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjEyODAiLCJqdGkiOiJiYzBlY2NlOC05ZGY0LTQzZDYtYTVhMC0wMjI1MzY2YmM4M2EiLCJzdWIiOiIzOWYxMWMxMC0wNjkzLTQxZWQtOWJlYy04MDExZTI3MjE1NjIifQ.PUcnACCdwqfWRGRzF8lG6xDTgHKAwKV6eTw8tHFuNBXaUNbqExBwUQEW0-cCHsV-nLEyhxyjhXmVCkIDgz-ukKfS0xStiDrJQbiq8m0auodkArmJSsYzElXkKdv37FHu0t-CGoXptdLyuo9eCnzzmci3ev18zMR5HjYMCQEclELV6OEICNr_0EwhAGJa1yX6ODYrLMZ3SdEd6fj-ZGX7j9owTs6iEsqCB_TORfnGGg6lEINE5GlYsyp7JUxolS6H4lPeN5h2mxk2_OkJY8GX3ydv75LsIZ-jjL3xC5XncCESrefgDabib1fudJ4038D0EzqTcOREPAqmjWhnDhTulQ", + "token": "bc0ecce8-9df4-43d6-a5a0-0225366bc83a" + } + }, + "permissions": [] + } +} +``` + + + +### What To Do +Use the new JWT format to: + +verify the signature of the JWT to match the iss URL's TSL presented certificates +construct the enrollment url from the JWTs properties in the following format: + +``` + + "/enroll?token=" + +``` + +## Multiple Invalid Value Error Handling +Errors where there is the potential to report about multiple invalid field values for a given field used to report as a separate error for each value. Now there will be one error, but the values field will hold the invalid values. + +### Old Format +``` +{ + "error": { + "args": { + "urlVars": { + "id": "097018b6-108e-42b3-869b-deb9e1814594" + } + }, + "cause": { + "errors": [ + { + "message": "entity not found for id [06ecf930-3a9f-4a6c-98b5-8f0be1bde9e2]", + "field": "ids[0]", + "value": "06ecf930-3a9f-4a6c-98b5-8f0be1bde9e2" + } + ] + }, + "causeMessage": "There were multiple field errors: the value '06ecf930-3a9f-4a6c-9...' for 'ids[0]' is invalid: entity not found for id [06ecf930-3a9f-4a6c-98b5-8f0be1bde9e2]", + "code": "INVALID_FIELD", + "message": "The field contains an invalid value", + "requestId": "48ea4bce-f233-410e-a062-5dbceee20223" + }, + "meta": { + "apiEnrolmentVersion": "0.0.1", + "apiVersion": "0.0.1" + } +} +``` + +### New Format +``` +{ + "error": { + "args": { + "urlVars": { + "id": "5b15c442-5590-4c58-8bc7-0da788e0cfcf" + } + }, + "cause": { + "message": "clusters(s) not found", + "field": "clusters", + "value": [ + "68f8739f-cf52-4d51-9553-dfe7cf9c6a03" + ] + }, + "causeMessage": "the value '[68f8739f-cf52-4d51-9553-dfe7cf9c6a03]' for 'clusters' is invalid: clusters(s) not found", + "code": "INVALID_FIELD", + "message": "The field contains an invalid value", + "requestId": "ab6553e8-e9b1-408c-9fed-11cc627cfd84" + }, + "meta": { + "apiEnrolmentVersion": "0.0.1", + "apiVersion": "0.0.1" + } +} +``` + + \ No newline at end of file diff --git a/etc/001.transwarp.yml b/etc/001.transwarp.yml new file mode 100644 index 000000000..d420e5ecf --- /dev/null +++ b/etc/001.transwarp.yml @@ -0,0 +1,72 @@ +v: 3 + +identity: + cert: etc/ca/intermediate/certs/001-client.cert.pem + server_cert: etc/ca/intermediate/certs/001-server.cert.pem + key: etc/ca/intermediate/private/001.key.pem + ca: etc/ca/intermediate/certs/ca-chain.cert.pem + +# Configure the forwarder options +# +forwarder: + # How frequently does the forwarder probe the link latency. This will ultimately determine the resolution of the + # responsiveness available to smart routing. This resolution comes at the expense of bandwidth utilization for the + # probes, control plane utilization, and CPU utilization processing the results. + # + latencyProbeInterval: 1000 + +#trace: +# path: 001.trace + +#profile: +# memory: +# path: 001.memprof +# cpu: +# path: 001.cpuprof + +ctrl: + endpoint: tls:127.0.0.1:6262 + +link: + dialers: + - binding: transwarp + bind: :0 + +listeners: + # basic ssh proxy + - binding: proxy + address: tcp:0.0.0.0:1122 + service: ssh + options: + mtu: 10240 + + # for iperf_tcp (iperf3) + - binding: proxy + address: tcp:0.0.0.0:7001 + service: iperf + + # for iperf_udp (iperf3) + - binding: proxy_udp + address: udp:0.0.0.0:7001 + service: iperf_udp + + # example xgress_transport + - binding: transport + address: tls:0.0.0.0:7002 + options: + retransmission: true + randomDrops: true + drop1InN: 5000 + + # example xgress_udp + - binding: transport_udp + address: udp:0.0.0.0:7003 + options: + retransmission: true + randomDrops: true + drop1InN: 5000 + +# xctrl_example +# +#example: +# delay: 1 diff --git a/etc/001.yml b/etc/001.yml index f16539cc2..602d0c5c4 100644 --- a/etc/001.yml +++ b/etc/001.yml @@ -1,4 +1,4 @@ -v: 2 +v: 3 identity: cert: etc/ca/intermediate/certs/001-client.cert.pem @@ -27,11 +27,17 @@ forwarder: ctrl: endpoint: tls:127.0.0.1:6262 +link: + dialers: + - binding: transport + listeners: # basic ssh proxy - binding: proxy address: tcp:0.0.0.0:1122 service: ssh + options: + mtu: 768 # for iperf_tcp (iperf3) - binding: proxy @@ -52,7 +58,7 @@ listeners: drop1InN: 5000 # example xgress_udp - - binding: udp + - binding: transport_udp address: udp:0.0.0.0:7003 options: retransmission: true diff --git a/etc/002.transwarp.yml b/etc/002.transwarp.yml new file mode 100644 index 000000000..3b88de601 --- /dev/null +++ b/etc/002.transwarp.yml @@ -0,0 +1,28 @@ +v: 3 + +identity: + cert: etc/ca/intermediate/certs/002-client.cert.pem + server_cert: etc/ca/intermediate/certs/002-server.cert.pem + key: etc/ca/intermediate/private/002.key.pem + ca: etc/ca/intermediate/certs/ca-chain.cert.pem + +#trace: +# path: 002.trace + +ctrl: + endpoint: tls:127.0.0.1:6262 + +link: + listeners: + - binding: transwarp + bind: 127.0.0.1:6002 +# listeners: +# - binding: transport +# bind: tls:127.0.0.1:6002 +# advertise: tls:127.0.0.1:6002 +# options: +# outQueueSize: 16 +# dialers: +# - binding: transport +# options: +# outQueueSize: 32 \ No newline at end of file diff --git a/etc/002.yml b/etc/002.yml index aebab86c0..cfe0a17b3 100644 --- a/etc/002.yml +++ b/etc/002.yml @@ -1,4 +1,4 @@ -v: 2 +v: 3 identity: cert: etc/ca/intermediate/certs/002-client.cert.pem @@ -13,9 +13,13 @@ ctrl: endpoint: tls:127.0.0.1:6262 link: - listener: quic:127.0.0.1:6002 - -listeners: - - binding: transport - address: tls:0.0.0.0:7002 # make sure we don't conflict with router 001 - + listeners: + - binding: transport + bind: tls:127.0.0.1:6002 + advertise: tls:127.0.0.1:6002 + options: + outQueueSize: 16 + dialers: + - binding: transport + options: + outQueueSize: 32 \ No newline at end of file diff --git a/etc/003.transwarp.yml b/etc/003.transwarp.yml new file mode 100644 index 000000000..f295c8df2 --- /dev/null +++ b/etc/003.transwarp.yml @@ -0,0 +1,37 @@ +v: 3 + +identity: + cert: etc/ca/intermediate/certs/003-client.cert.pem + server_cert: etc/ca/intermediate/certs/003-server.cert.pem + key: etc/ca/intermediate/private/003.key.pem + ca: etc/ca/intermediate/certs/ca-chain.cert.pem + +# Configure the forwarder options +# +forwarder: + # How frequently does the forwarder probe the link latency. This will ultimately determine the resolution of the + # responsiveness available to smart routing. This resolution comes at the expense of bandwidth utilization for the + # probes, control plane utilization, and CPU utilization processing the results. + # + latencyProbeInterval: 1000 + +#trace: +# path: 003.trace + +#profile: +# memory: +# path: 003.memprof +# intervalMs: 5000 + +ctrl: + endpoint: tls:127.0.0.1:6262 + +link: + dialers: + - binding: transwarp + bind: :0 + +dialers: + - binding: transport + options: + mtu: 10240 \ No newline at end of file diff --git a/etc/003.yml b/etc/003.yml index 3ebeae44e..d4c7b515b 100644 --- a/etc/003.yml +++ b/etc/003.yml @@ -1,4 +1,4 @@ -v: 2 +v: 3 identity: cert: etc/ca/intermediate/certs/003-client.cert.pem @@ -26,6 +26,10 @@ forwarder: ctrl: endpoint: tls:127.0.0.1:6262 +link: + dialers: + - binding: transport + dialers: - binding: transport options: diff --git a/etc/004.yml b/etc/004.yml index ebc43b1fc..c27bd34a1 100644 --- a/etc/004.yml +++ b/etc/004.yml @@ -1,4 +1,4 @@ -v: 2 +v: 3 identity: cert: etc/ca/intermediate/certs/004-client.cert.pem @@ -22,4 +22,8 @@ ctrl: endpoint: tls:127.0.0.1:6262 link: - listener: quic:127.0.0.1:6004 + listeners: + - binding: transport + bind: tls:127.0.0.1:6004 + dialers: + - binding: transport \ No newline at end of file diff --git a/etc/edge.router.yml b/etc/edge.router.yml index 018e49528..d85c33e89 100644 --- a/etc/edge.router.yml +++ b/etc/edge.router.yml @@ -1,4 +1,4 @@ -v: 2 +v: 3 # (required) The certificates, ca chains, and private key used to represent this routers identity # @@ -32,6 +32,10 @@ identity: ctrl: endpoint: tls:127.0.0.1:6262 +link: + dialers: + - binding: transport + # By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this # section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge # Router. diff --git a/go.mod b/go.mod index 52d413acf..798348e7a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/netfoundry/ziti-cmd -go 1.13 +go 1.14 // replace github.com/netfoundry/ziti-foundation => ../ziti-foundation @@ -24,10 +24,10 @@ require ( github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.0.0-20190813191113-2be43bd0dccc - github.com/netfoundry/ziti-edge v0.12.20 - github.com/netfoundry/ziti-fabric v0.11.6 - github.com/netfoundry/ziti-foundation v0.9.1 - github.com/netfoundry/ziti-sdk-golang v0.11.9 + github.com/netfoundry/ziti-edge v0.13.2 + github.com/netfoundry/ziti-fabric v0.11.12 + github.com/netfoundry/ziti-foundation v0.9.7 + github.com/netfoundry/ziti-sdk-golang v0.11.15 github.com/pborman/uuid v1.2.0 github.com/pkg/errors v0.9.1 github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 diff --git a/go.sum b/go.sum index de0757973..7fb999893 100644 --- a/go.sum +++ b/go.sum @@ -146,8 +146,6 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e h1:txQltCyjXAqVVSZDArPEhUTg35hKwVIuXwtQo7eAMNQ= -github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE= @@ -226,23 +224,18 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/netfoundry/secretstream v0.1.1 h1:z6T7B5DuOtr9O+SmKaS9DzwOoGLYtgvyTzuPuR5FO7I= github.com/netfoundry/secretstream v0.1.1/go.mod h1:uasYkYSp0MmNSlKOWJ2sVzxPms8e58TS4ENq4yro86k= -github.com/netfoundry/ziti-edge v0.12.0 h1:NU/PE5hYNr4A9dCqSmEpDihKHYbW9E5G+R+3If3nFkA= -github.com/netfoundry/ziti-edge v0.12.0/go.mod h1:/50mZCqBHDTsX7RN84qPGjiveWbzF0knL75DzZOmwD0= -github.com/netfoundry/ziti-edge v0.12.20 h1:xbSY/6GVHyjrG5qWPOLQpSPbYsY4Ta6MbahKf+xw08A= -github.com/netfoundry/ziti-edge v0.12.20/go.mod h1:uJX7aDzgaiER/aFW3FvkrvrMh7V7+ivvecwy3gg7ydA= -github.com/netfoundry/ziti-fabric v0.11.0 h1:4GQqtsK1VWnMVEth6EPkvua/YX0AOC3UAn4/EiEbvKA= -github.com/netfoundry/ziti-fabric v0.11.0/go.mod h1:kjtZ81Matol9D/HL05MG+/l8BceQ+0eayWaU6LQo9js= -github.com/netfoundry/ziti-fabric v0.11.6 h1:LDZfauNOwpb5akv4T7zWZO4raUSp18zs10NCvrhpOw8= -github.com/netfoundry/ziti-fabric v0.11.6/go.mod h1:iHhHqmnMep+ytDuBkhm6GLbgTXEEX9dM0aBUimpknps= -github.com/netfoundry/ziti-foundation v0.7.0 h1:Lrcq88sosUg0w0lwO4iU0ksiFB1q6H4ZPf7vUMLtPas= -github.com/netfoundry/ziti-foundation v0.7.0/go.mod h1:MK2ajCpS40MtiZFnMYjKIBDTQFDWwgqNq+RxypNjl9U= -github.com/netfoundry/ziti-foundation v0.9.0/go.mod h1:EhrF0tVGajmQYeCEz7BOHFK5D4alnoQsRz0HHTjNuvE= -github.com/netfoundry/ziti-foundation v0.9.1 h1:9hqYRb+XTJ5ZlaqVgukgTNdnis2DsCv9TcoUKRc1WtQ= -github.com/netfoundry/ziti-foundation v0.9.1/go.mod h1:GN+ALX+7zr1e4vcI2j6VRbaDVcF0wnuih0p9vj22Of0= -github.com/netfoundry/ziti-sdk-golang v0.11.1 h1:TqCEGo4d3yBQ8a5MLJBrgWvlRd0BtaB2wJk7uXMlW8w= -github.com/netfoundry/ziti-sdk-golang v0.11.1/go.mod h1:BSP+tnw+s1qp7DcjoifofQtpkkgt7mwDoPSIe9D7w8s= -github.com/netfoundry/ziti-sdk-golang v0.11.9 h1:BoOBAzmOMleumbvFo5/JR8VCrPymhfYE+P/dZNmL5vo= -github.com/netfoundry/ziti-sdk-golang v0.11.9/go.mod h1:pX49Kt4NoTM3ecvQ6Ca+B+Jw4HmoNkdHeKYR3t52xa8= +github.com/netfoundry/ziti-edge v0.13.2 h1:+MR+B5pFw/y9llQXowNukm2wyhmaFPXZjqY8YRUxpoU= +github.com/netfoundry/ziti-edge v0.13.2/go.mod h1:0MLtDEOXUv6cYNiIW0VpnmR/dkfFez1yaWS4oBPT/8M= +github.com/netfoundry/ziti-fabric v0.11.11 h1:G6xaDziZUPO5W1bzxlSp7toJ95CkXpkhA9BIxdnsUcM= +github.com/netfoundry/ziti-fabric v0.11.11/go.mod h1:b4KUJ05JJkK9jmIlXy4TODXIgLHTdoruPe0EJ5HJHPg= +github.com/netfoundry/ziti-fabric v0.11.12 h1:4u2p++waMZhpX2BDxi0j/0FHWWPkAEXyrT+0K0ZzYTc= +github.com/netfoundry/ziti-fabric v0.11.12/go.mod h1:JBlXIsRxF2NuXVez7E0UlZBwatqH7Rm2g+12YeiIziI= +github.com/netfoundry/ziti-foundation v0.9.6 h1:rsZlM05qAa1PERTqcM4YeCilbCd1i95GbGUzh9OdgKU= +github.com/netfoundry/ziti-foundation v0.9.6/go.mod h1:desAxe5jN/V/+cYe99TGEqxtMVdlJ1HfSRzCmuPJD7M= +github.com/netfoundry/ziti-foundation v0.9.7 h1:ioFQB8uQOBY/fKjJcgGISgqNJbsrDOqNmhki1LSLZ7A= +github.com/netfoundry/ziti-foundation v0.9.7/go.mod h1:desAxe5jN/V/+cYe99TGEqxtMVdlJ1HfSRzCmuPJD7M= +github.com/netfoundry/ziti-sdk-golang v0.11.15 h1:+BJ1Kn3PQvmT4FkEfr5R8oedvBJJCOSu06kIZ9GUM18= +github.com/netfoundry/ziti-sdk-golang v0.11.15/go.mod h1:MpEYu9L4y4/oXgMUq5+MigYXA67c09iUxDeQmy2lLFE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oleiade/reflections v1.0.0 h1:0ir4pc6v8/PJ0yw5AEtMddfXpWBXg9cnG7SgSoJuCgY= github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w= @@ -283,8 +276,6 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ= -github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -474,9 +465,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/version b/version index c43e1055f..f3040840f 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.12 +0.13 diff --git a/ziti-fabric-test/subcmd/client/http.go b/ziti-fabric-test/subcmd/client/http.go index bbdc883bc..774d48821 100644 --- a/ziti-fabric-test/subcmd/client/http.go +++ b/ziti-fabric-test/subcmd/client/http.go @@ -17,15 +17,15 @@ package client import ( - "github.com/netfoundry/ziti-cmd/ziti-fabric-test/subcmd" - "github.com/netfoundry/ziti-fabric/xgress_transport" - "github.com/netfoundry/ziti-foundation/identity/dotziti" - "github.com/netfoundry/ziti-foundation/identity/identity" - "github.com/netfoundry/ziti-foundation/transport" "context" "crypto/tls" "fmt" "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-cmd/ziti-fabric-test/subcmd" + "github.com/netfoundry/ziti-fabric/router/xgress_transport" + "github.com/netfoundry/ziti-foundation/identity/dotziti" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" "github.com/spf13/cobra" "io/ioutil" "net" diff --git a/ziti-fabric-test/subcmd/client/nc.go b/ziti-fabric-test/subcmd/client/nc.go index 161f37fb3..537cc4ee9 100644 --- a/ziti-fabric-test/subcmd/client/nc.go +++ b/ziti-fabric-test/subcmd/client/nc.go @@ -17,14 +17,14 @@ package client import ( + "fmt" + "github.com/michaelquigley/pfxlog" "github.com/netfoundry/ziti-cmd/ziti-fabric-test/subcmd" - "github.com/netfoundry/ziti-fabric/xgress_transport" + "github.com/netfoundry/ziti-fabric/router/xgress_transport" "github.com/netfoundry/ziti-foundation/identity/dotziti" "github.com/netfoundry/ziti-foundation/identity/identity" "github.com/netfoundry/ziti-foundation/transport" "github.com/netfoundry/ziti-foundation/transport/udp" - "fmt" - "github.com/michaelquigley/pfxlog" "github.com/spf13/cobra" "io" "os" diff --git a/ziti-fabric-test/subcmd/loop2/dialer.go b/ziti-fabric-test/subcmd/loop2/dialer.go index 01223d8a7..f5399b3a0 100644 --- a/ziti-fabric-test/subcmd/loop2/dialer.go +++ b/ziti-fabric-test/subcmd/loop2/dialer.go @@ -20,7 +20,7 @@ import ( "fmt" "github.com/michaelquigley/pfxlog" "github.com/netfoundry/ziti-cmd/ziti-fabric-test/subcmd/loop2/pb" - "github.com/netfoundry/ziti-fabric/xgress_transport" + "github.com/netfoundry/ziti-fabric/router/xgress_transport" "github.com/netfoundry/ziti-foundation/identity/dotziti" "github.com/netfoundry/ziti-foundation/identity/identity" "github.com/netfoundry/ziti-foundation/transport" diff --git a/ziti-fabric-test/subcmd/loop3/dialer.go b/ziti-fabric-test/subcmd/loop3/dialer.go index 73fc19e0b..ca0ef04dc 100644 --- a/ziti-fabric-test/subcmd/loop3/dialer.go +++ b/ziti-fabric-test/subcmd/loop3/dialer.go @@ -20,7 +20,7 @@ import ( "fmt" "github.com/michaelquigley/pfxlog" loop3_pb "github.com/netfoundry/ziti-cmd/ziti-fabric-test/subcmd/loop3/pb" - "github.com/netfoundry/ziti-fabric/xgress_transport" + "github.com/netfoundry/ziti-fabric/router/xgress_transport" "github.com/netfoundry/ziti-foundation/identity/dotziti" "github.com/netfoundry/ziti-foundation/identity/identity" "github.com/netfoundry/ziti-foundation/transport" diff --git a/ziti-fabric/subcmd/stream_traces.go b/ziti-fabric/subcmd/stream_traces.go index c5884fee7..c18e34e35 100644 --- a/ziti-fabric/subcmd/stream_traces.go +++ b/ziti-fabric/subcmd/stream_traces.go @@ -17,14 +17,14 @@ package subcmd import ( - "github.com/netfoundry/ziti-foundation/channel2" - "github.com/netfoundry/ziti-fabric/pb/ctrl_pb" - "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" - "github.com/netfoundry/ziti-fabric/xgress" - "github.com/netfoundry/ziti-foundation/trace/pb" "errors" "fmt" "github.com/golang/protobuf/proto" + "github.com/netfoundry/ziti-fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-fabric/router/xgress" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/trace/pb" "github.com/spf13/cobra" "sort" "time" diff --git a/ziti-router/main.go b/ziti-router/main.go index 6899c73ab..6c50236d4 100644 --- a/ziti-router/main.go +++ b/ziti-router/main.go @@ -18,7 +18,9 @@ package main import ( "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-cmd/common/version" "github.com/netfoundry/ziti-cmd/ziti-router/subcmd" + "github.com/netfoundry/ziti-edge/build" "github.com/netfoundry/ziti-foundation/transport" "github.com/netfoundry/ziti-foundation/transport/quic" "github.com/netfoundry/ziti-foundation/transport/tcp" @@ -32,6 +34,8 @@ func init() { transport.AddAddressParser(quic.AddressParser{}) transport.AddAddressParser(tls.AddressParser{}) transport.AddAddressParser(tcp.AddressParser{}) + + build.InitBuildInfo(version.GetCmdBuildInfo()) } func main() { diff --git a/ziti-router/subcmd/run.go b/ziti-router/subcmd/run.go index 706350670..dcb7874d4 100644 --- a/ziti-router/subcmd/run.go +++ b/ziti-router/subcmd/run.go @@ -19,7 +19,7 @@ package subcmd import ( "github.com/netfoundry/ziti-edge/gateway/xgress_edge" "github.com/netfoundry/ziti-fabric/router" - "github.com/netfoundry/ziti-fabric/xgress" + "github.com/netfoundry/ziti-fabric/router/xgress" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -45,15 +45,15 @@ func run(cmd *cobra.Command, args []string) { xgressEdgeFactory := xgress_edge.NewFactory() xgress.GlobalRegistry().Register("edge", xgressEdgeFactory) if err := r.RegisterXctrl(xgressEdgeFactory); err != nil { - logrus.Panicf("error registering edge in framework (%w)", err) + logrus.Panicf("error registering edge in framework (%v)", err) } if err := r.Run(); err != nil { - logrus.Panicf("error starting (%w)", err) + logrus.Panicf("error starting (%v)", err) } } else { - logrus.Panicf("error loading configuration (%w)", err) + logrus.Panicf("error loading configuration (%v)", err) } } diff --git a/ziti/cmd/ziti/cmd/edge_controller/common.go b/ziti/cmd/ziti/cmd/edge_controller/common.go index 2f8d6a588..ede232643 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/common.go +++ b/ziti/cmd/ziti/cmd/edge_controller/common.go @@ -51,6 +51,21 @@ func mapNameToID(entityType string, val string) (string, error) { return entityId, nil } +func mapIdToName(entityType string, val string) (string, error) { + list, err := filterEntitiesOfType(entityType, fmt.Sprintf(`id="%s"`, val), false, nil) + if err != nil { + return "", err + } + + if len(list) < 1 { + return "", errors.Errorf("no %v found for id %v", entityType, val) + } + + entity := list[0] + name, _ := entity.Path("name").Data().(string) + return name, nil +} + func mapNamesToIDs(entityType string, list ...string) ([]string, error) { var result []string for _, val := range list { diff --git a/ziti/cmd/ziti/cmd/edge_controller/create.go b/ziti/cmd/ziti/cmd/edge_controller/create.go index 7673bc9e2..57b41f3e9 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/create.go +++ b/ziti/cmd/ziti/cmd/edge_controller/create.go @@ -41,6 +41,7 @@ func newCreateCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com cmd.AddCommand(newCreateAuthenticatorCmd(f, out, errOut)) cmd.AddCommand(newCreateCaCmd(f, out, errOut)) cmd.AddCommand(newCreateConfigCmd(f, out, errOut)) + cmd.AddCommand(newCreateConfigTypeCmd(f, out, errOut)) cmd.AddCommand(newCreateEdgeRouterCmd(f, out, errOut)) cmd.AddCommand(newCreateEdgeRouterPolicyCmd(f, out, errOut)) cmd.AddCommand(newCreateTerminatorCmd(f, out, errOut)) diff --git a/ziti/cmd/ziti/cmd/edge_controller/create_config.go b/ziti/cmd/ziti/cmd/edge_controller/create_config.go index edcffa88c..6218027f9 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/create_config.go +++ b/ziti/cmd/ziti/cmd/edge_controller/create_config.go @@ -72,9 +72,14 @@ func runCreateConfig(o *createConfigOptions) error { return errors.Errorf("unable to parse data as json: %v", err) } + configTypeId, err := mapNameToID("config-types", o.Args[1]) + if err != nil { + return err + } + entityData := gabs.New() setJSONValue(entityData, o.Args[0], "name") - setJSONValue(entityData, o.Args[1], "type") + setJSONValue(entityData, configTypeId, "type") setJSONValue(entityData, dataMap, "data") result, err := createEntityOfType("configs", entityData.String(), &o.commonOptions) diff --git a/ziti/cmd/ziti/cmd/edge_controller/create_config_type.go b/ziti/cmd/ziti/cmd/edge_controller/create_config_type.go new file mode 100644 index 000000000..bd5c212e8 --- /dev/null +++ b/ziti/cmd/ziti/cmd/edge_controller/create_config_type.go @@ -0,0 +1,98 @@ +/* + 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 edge_controller + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/pkg/errors" + + "github.com/Jeffail/gabs" + "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/common" + cmdutil "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/factory" + cmdhelper "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/helpers" + "github.com/spf13/cobra" +) + +type createConfigTypeOptions struct { + commonOptions +} + +// newCreateConfigTypeCmd creates the 'edge controller create service-policy' command +func newCreateConfigTypeCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { + options := &createConfigTypeOptions{ + commonOptions: commonOptions{ + CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut}, + }, + } + + cmd := &cobra.Command{ + Use: "config-type ", + Short: "creates a config type managed by the Ziti Edge Controller", + Long: "creates a config type managed by the Ziti Edge Controller", + Args: cobra.RangeArgs(1, 2), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := runCreateConfigType(options) + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") + + return cmd +} + +// runCreateConfigType create a new configType on the Ziti Edge Controller +func runCreateConfigType(o *createConfigTypeOptions) error { + var schemaMap map[string]interface{} + + if len(o.Args) == 2 { + schemaMap = map[string]interface{}{} + if err := json.Unmarshal([]byte(o.Args[1]), &schemaMap); err != nil { + fmt.Printf("Attempted to parse: %v\n", o.Args[1]) + fmt.Printf("Failing parsing JSON: %+v\n", err) + return errors.Errorf("unable to parse data as json: %v", err) + } + } + + entityData := gabs.New() + setJSONValue(entityData, o.Args[0], "name") + if schemaMap != nil { + setJSONValue(entityData, schemaMap, "schema") + } + + result, err := createEntityOfType("config-types", entityData.String(), &o.commonOptions) + + if err != nil { + panic(err) + } + + configTypeId := result.S("data", "id").Data() + + if _, err := fmt.Fprintf(o.Out, "%v\n", configTypeId); err != nil { + panic(err) + } + + return err +} diff --git a/ziti/cmd/ziti/cmd/edge_controller/create_service.go b/ziti/cmd/ziti/cmd/edge_controller/create_service.go index 86b74e017..f33731ae3 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/create_service.go +++ b/ziti/cmd/ziti/cmd/edge_controller/create_service.go @@ -74,13 +74,19 @@ func newCreateServiceCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *co // runCreateService implements the command to create a service func runCreateService(o *createServiceOptions) (err error) { + + configs, err := mapNamesToIDs("configs", o.configs...) + if err != nil { + return err + } + entityData := gabs.New() setJSONValue(entityData, o.Args[0], "name") if o.terminatorStrategy != "" { setJSONValue(entityData, o.terminatorStrategy, "terminatorStrategy") } setJSONValue(entityData, o.roleAttributes, "roleAttributes") - setJSONValue(entityData, o.configs, "configs") + setJSONValue(entityData, configs, "configs") setJSONValue(entityData, o.tags, "tags") result, err := createEntityOfType("services", entityData.String(), &o.commonOptions) diff --git a/ziti/cmd/ziti/cmd/edge_controller/delete.go b/ziti/cmd/ziti/cmd/edge_controller/delete.go index d45ea5358..1ef04c57a 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/delete.go +++ b/ziti/cmd/ziti/cmd/edge_controller/delete.go @@ -54,6 +54,7 @@ func newDeleteCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Com cmd.AddCommand(newDeleteAuthenticatorCmd("authenticator", newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("ca", runDeleteEntityOfType, newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("config", runDeleteEntityOfType, newOptions())) + cmd.AddCommand(newDeleteCmdForEntityType("config-type", runDeleteEntityOfType, newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("edge-router", runDeleteEntityOfType, newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("edge-router-policy", runDeleteEntityOfType, newOptions())) cmd.AddCommand(newDeleteCmdForEntityType("identity", runDeleteEntityOfType, newOptions())) diff --git a/ziti/cmd/ziti/cmd/edge_controller/list.go b/ziti/cmd/ziti/cmd/edge_controller/list.go index 72c04a6c4..e0683a0d5 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/list.go +++ b/ziti/cmd/ziti/cmd/edge_controller/list.go @@ -56,22 +56,27 @@ func newListCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma cmd.AddCommand(newListCmdForEntityType("cas", runListCAs, newOptions())) cmd.AddCommand(newListCmdForEntityType("config-types", runListConfigTypes, newOptions())) cmd.AddCommand(newListCmdForEntityType("configs", runListConfigs, newOptions())) - cmd.AddCommand(newListCmdForEntityType("edge-routers", runListEdgeRouters, newOptions())) + cmd.AddCommand(newListEdgeRoutersCmd(newOptions())) cmd.AddCommand(newListCmdForEntityType("edge-router-policies", runListEdgeRouterPolicies, newOptions())) cmd.AddCommand(newListCmdForEntityType("terminators", runListTerminators, newOptions())) - cmd.AddCommand(newListCmdForEntityType("gateways", runListEdgeRouters, newOptions())) - cmd.AddCommand(newListCmdForEntityType("identities", runListIdentities, newOptions())) + cmd.AddCommand(newListIdentitiesCmd(newOptions())) cmd.AddCommand(newListServicesCmd(newOptions())) cmd.AddCommand(newListCmdForEntityType("service-edge-router-policies", runListServiceEdgeRouterPolices, newOptions())) cmd.AddCommand(newListCmdForEntityType("service-policies", runListServicePolices, newOptions())) cmd.AddCommand(newListCmdForEntityType("sessions", runListSessions, newOptions())) + cmd.AddCommand(newListCmdForEntityType("edge-router-role-attributes", runListEdgeRouterRoleAttributes, newOptions())) + cmd.AddCommand(newListCmdForEntityType("identity-role-attributes", runListIdentityRoleAttributes, newOptions())) + cmd.AddCommand(newListCmdForEntityType("service-role-attributes", runListServiceRoleAttributes, newOptions())) + configTypeListRootCmd := newEntityListRootCmd("config-type") configTypeListRootCmd.AddCommand(newSubListCmdForEntityType("config-type", "configs", outputConfigs, newOptions())) edgeRouterListRootCmd := newEntityListRootCmd("edge-router") - edgeRouterListRootCmd.AddCommand(newSubListCmdForEntityType("edge-router", "edge-router-policies", outputEdgeRouterPolicies, newOptions())) - edgeRouterListRootCmd.AddCommand(newSubListCmdForEntityType("edge-router", "service-edge-router-polices", outputServiceEdgeRouterPolicies, newOptions())) + edgeRouterListRootCmd.AddCommand(newSubListCmdForEntityType("edge-routers", "edge-router-policies", outputEdgeRouterPolicies, newOptions())) + edgeRouterListRootCmd.AddCommand(newSubListCmdForEntityType("edge-routers", "service-edge-router-polices", outputServiceEdgeRouterPolicies, newOptions())) + edgeRouterListRootCmd.AddCommand(newSubListCmdForEntityType("edge-routers", "identities", outputIdentities, newOptions())) + edgeRouterListRootCmd.AddCommand(newSubListCmdForEntityType("edge-routers", "services", outputServices, newOptions())) edgeRouterPolicyListRootCmd := newEntityListRootCmd("edge-router-policy") edgeRouterPolicyListRootCmd.AddCommand(newSubListCmdForEntityType("edge-router-policies", "edge-routers", outputEdgeRouters, newOptions())) @@ -79,13 +84,17 @@ func newListCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma identityListRootCmd := newEntityListRootCmd("identity") identityListRootCmd.AddCommand(newSubListCmdForEntityType("identities", "edge-router-policies", outputEdgeRouterPolicies, newOptions())) + identityListRootCmd.AddCommand(newSubListCmdForEntityType("identities", "edge-routers", outputEdgeRouters, newOptions())) identityListRootCmd.AddCommand(newSubListCmdForEntityType("identities", "service-policies", outputServicePolicies, newOptions())) + identityListRootCmd.AddCommand(newSubListCmdForEntityType("identities", "services", outputServices, newOptions())) serviceListRootCmd := newEntityListRootCmd("service") serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "configs", outputConfigs, newOptions())) serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "service-policies", outputServicePolicies, newOptions())) serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "service-edge-router-policies", outputServiceEdgeRouterPolicies, newOptions())) serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "terminators", outputTerminators, newOptions())) + serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "identities", outputIdentities, newOptions())) + serviceListRootCmd.AddCommand(newSubListCmdForEntityType("services", "edge-routers", outputEdgeRouters, newOptions())) serviceEdgeRouterPolicyListRootCmd := newEntityListRootCmd("service-edge-router-policy") serviceEdgeRouterPolicyListRootCmd.AddCommand(newSubListCmdForEntityType("service-edge-router-policies", "services", outputServices, newOptions())) @@ -141,10 +150,12 @@ func newListCmdForEntityType(entityType string, command listCommandRunner, optio return cmd } -// newListCmdForEntityType creates the list command for the given entity type +// newListServicesCmd creates the list command for the given entity type func newListServicesCmd(options *commonOptions) *cobra.Command { var asIdentity string var configTypes string + var roleFilters []string + var roleSemantic string cmd := &cobra.Command{ Use: "services ?", @@ -154,7 +165,7 @@ func newListServicesCmd(options *commonOptions) *cobra.Command { Run: func(cmd *cobra.Command, args []string) { options.Cmd = cmd options.Args = args - err := runListServices(asIdentity, configTypes, options) + err := runListServices(asIdentity, configTypes, roleFilters, roleSemantic, options) cmdhelper.CheckErr(err) }, SuggestFor: []string{}, @@ -166,6 +177,66 @@ func newListServicesCmd(options *commonOptions) *cobra.Command { cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") cmd.Flags().StringVar(&asIdentity, "as-identity", "", "Allow admins to see services as they would be seen by a different identity") cmd.Flags().StringVar(&configTypes, "config-types", "", "Override which config types to view on services") + cmd.Flags().StringSliceVar(&roleFilters, "role-filters", nil, "Allow filtering by roles") + cmd.Flags().StringVar(&roleSemantic, "role-semantic", "", "Specify which roles semantic to use ") + + return cmd +} + +// newListEdgeRoutersCmd creates the list command for the given entity type +func newListEdgeRoutersCmd(options *commonOptions) *cobra.Command { + var roleFilters []string + var roleSemantic string + + cmd := &cobra.Command{ + Use: "edge-routers ?", + Short: "lists edge routers managed by the Ziti Edge Controller", + Long: "lists edge routers managed by the Ziti Edge Controller", + Args: cobra.MaximumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := runListEdgeRouters(roleFilters, roleSemantic, options) + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + + cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") + cmd.Flags().StringSliceVar(&roleFilters, "role-filters", nil, "Allow filtering by roles") + cmd.Flags().StringVar(&roleSemantic, "role-semantic", "", "Specify which roles semantic to use ") + + return cmd +} + +// newListEdgeRoutersCmd creates the list command for the given entity type +func newListIdentitiesCmd(options *commonOptions) *cobra.Command { + var roleFilters []string + var roleSemantic string + + cmd := &cobra.Command{ + Use: "identities ?", + Short: "lists identities managed by the Ziti Edge Controller", + Long: "lists identities managed by the Ziti Edge Controller", + Args: cobra.MaximumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := runListIdentities(roleFilters, roleSemantic, options) + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + + cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") + cmd.Flags().StringSliceVar(&roleFilters, "role-filters", nil, "Allow filtering by roles") + cmd.Flags().StringVar(&roleSemantic, "role-semantic", "", "Specify which roles semantic to use ") return cmd } @@ -229,20 +300,33 @@ func filterSubEntitiesOfType(entityType, subType, entityId, filter string, o *co return nil, err } - return jsonParsed.S("data").Children() + children, err := jsonParsed.S("data").Children() + if err == gabs.ErrNotObjOrArray { + return nil, nil + } + return children, err } -func runListEdgeRouters(o *commonOptions) error { - children, err := listEntitiesWithOptions("edge-routers", o) +func runListEdgeRouters(roleFilters []string, roleSemantic string, options *commonOptions) error { + params := url.Values{} + if len(options.Args) > 0 { + params.Add("filter", options.Args[0]) + } + for _, roleFilter := range roleFilters { + params.Add("roleFilter", roleFilter) + } + if roleSemantic != "" { + params.Add("roleSemantic", roleSemantic) + } + children, err := listEntitiesOfType("edge-routers", params, options.OutputJSONResponse, options.Out) if err != nil { return err } - return outputEdgeRouters(o, children) + return outputEdgeRouters(options, children) } func outputEdgeRouters(o *commonOptions, children []*gabs.Container) error { - if o.OutputJSONResponse { return nil } @@ -312,7 +396,7 @@ func outputTerminators(o *commonOptions, children []*gabs.Container) error { return nil } -func runListServices(asIdentity string, configTypes string, options *commonOptions) error { +func runListServices(asIdentity string, configTypes string, roleFilters []string, roleSemantic string, options *commonOptions) error { params := url.Values{} if len(options.Args) > 0 { params.Add("filter", options.Args[0]) @@ -323,6 +407,12 @@ func runListServices(asIdentity string, configTypes string, options *commonOptio if configTypes != "" { params.Add("configTypes", configTypes) } + for _, roleFilter := range roleFilters { + params.Add("roleFilter", roleFilter) + } + if roleSemantic != "" { + params.Add("roleSemantic", roleSemantic) + } children, err := listEntitiesOfType("services", params, options.OutputJSONResponse, options.Out) if err != nil { return err @@ -403,12 +493,22 @@ func outputServicePolicies(o *commonOptions, children []*gabs.Container) error { } // runListIdentities implements the command to list identities -func runListIdentities(o *commonOptions) error { - children, err := listEntitiesWithOptions("identities", o) +func runListIdentities(roleFilters []string, roleSemantic string, options *commonOptions) error { + params := url.Values{} + if len(options.Args) > 0 { + params.Add("filter", options.Args[0]) + } + for _, roleFilter := range roleFilters { + params.Add("roleFilter", roleFilter) + } + if roleSemantic != "" { + params.Add("roleSemantic", roleSemantic) + } + children, err := listEntitiesOfType("identities", params, options.OutputJSONResponse, options.Out) if err != nil { return err } - return outputIdentities(o, children) + return outputIdentities(options, children) } // outputIdentities implements the command to list identities @@ -550,6 +650,38 @@ func runListSessions(o *commonOptions) error { return err } +func runListEdgeRouterRoleAttributes(o *commonOptions) error { + return runListRoleAttributes("edge-router", o) +} + +func runListIdentityRoleAttributes(o *commonOptions) error { + return runListRoleAttributes("identity", o) +} + +func runListServiceRoleAttributes(o *commonOptions) error { + return runListRoleAttributes("service", o) +} + +func runListRoleAttributes(entityType string, o *commonOptions) error { + children, err := listEntitiesWithOptions(entityType+"-role-attributes", o) + + if err != nil { + return err + } + + if o.OutputJSONResponse { + return nil + } + + for _, entity := range children { + if _, err := fmt.Fprintf(o.Out, "role-attribute: %v\n", entity.Data().(string)); err != nil { + return err + } + } + + return err +} + func runListChilden(parentType, childType string, o *commonOptions, outputF outputFunction) error { idOrName := o.Args[0] parentId, err := mapNameToID(parentType, idOrName) diff --git a/ziti/cmd/ziti/cmd/edge_controller/policy_advisor.go b/ziti/cmd/ziti/cmd/edge_controller/policy_advisor.go new file mode 100644 index 000000000..9975ced45 --- /dev/null +++ b/ziti/cmd/ziti/cmd/edge_controller/policy_advisor.go @@ -0,0 +1,402 @@ +/* + 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 edge_controller + +import ( + "fmt" + "github.com/Jeffail/gabs" + "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/common" + cmdutil "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/factory" + cmdhelper "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/cmd/helpers" + "github.com/netfoundry/ziti-cmd/ziti/cmd/ziti/util" + "github.com/spf13/cobra" + "io" +) + +// newPolicyAdvisor creates a command object for the "controller policy-advisor" command +func newPolicyAdivsorCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "policy-advisor", + Short: "runs sanity checks on various policy related entities managed by the Ziti Edge Controller", + Run: func(cmd *cobra.Command, args []string) { + err := cmd.Help() + cmdhelper.CheckErr(err) + }, + } + + cmd.AddCommand(newPolicyAdvisorIdentitiesCmd(f, out, errOut)) + cmd.AddCommand(newPolicyAdvisorServicesCmd(f, out, errOut)) + + return cmd +} + +type policyAdvisorOptions struct { + commonOptions + quiet bool +} + +// newPolicyAdvisorIdentitiesCmd creates the 'edge controller policy-advisor identities' command +func newPolicyAdvisorIdentitiesCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { + options := &policyAdvisorOptions{ + commonOptions: commonOptions{ + CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut}, + }, + } + + cmd := &cobra.Command{ + Use: "identities ? ?", + Short: "checks policies/connectivity between identities and services", + Args: cobra.RangeArgs(0, 2), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := runIdentitiesPolicyAdvisor(options) + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") + cmd.Flags().BoolVarP(&options.quiet, "quiet", "q", false, "Minimize output by hiding header") + + return cmd +} + +// newPolicyAdvisorServicesCmd creates the 'edge controller policy-advisor services' command +func newPolicyAdvisorServicesCmd(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { + options := &policyAdvisorOptions{ + commonOptions: commonOptions{ + CommonOptions: common.CommonOptions{Factory: f, Out: out, Err: errOut}, + }, + } + + cmd := &cobra.Command{ + Use: "services ? ?", + Short: "checks policies/connectivity between services and identities ", + Args: cobra.RangeArgs(0, 2), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := runServicesPolicyAdvisor(options) + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + cmd.Flags().BoolVarP(&options.OutputJSONResponse, "output-json", "j", false, "Output the full JSON response from the Ziti Edge Controller") + cmd.Flags().BoolVarP(&options.quiet, "quiet", "q", false, "Minimize output by hiding header") + + return cmd +} + +// runIdentitiesPolicyAdvisor create a new policyAdvisor on the Ziti Edge Controller +func runIdentitiesPolicyAdvisor(o *policyAdvisorOptions) error { + if len(o.Args) > 0 { + identityId, err := mapNameToID("identities", o.Args[0]) + if err != nil { + return err + } + if len(o.Args) > 1 { + serviceId, err := mapNameToID("services", o.Args[1]) + if err != nil { + return err + } + if err := outputHeader(o); err != nil { + return err + } + return runPolicyAdvisorForIdentityAndService(identityId, serviceId, o) + } + + if err := outputHeader(o); err != nil { + return err + } + return runPolicyAdvisorForIdentity(identityId, o) + } + + if err := outputHeader(o); err != nil { + return err + } + return runPolicyAdvisorForIdentities(o) +} + +// runServicesPolicyAdvisor create a new policyAdvisor on the Ziti Edge Controller +func runServicesPolicyAdvisor(o *policyAdvisorOptions) error { + if len(o.Args) > 0 { + serviceId, err := mapNameToID("services", o.Args[0]) + if err != nil { + return err + } + + if len(o.Args) > 1 { + identityId, err := mapNameToID("identities", o.Args[1]) + if err != nil { + return err + } + if err := outputHeader(o); err != nil { + return err + } + return runPolicyAdvisorForIdentityAndService(identityId, serviceId, o) + } + + if err := outputHeader(o); err != nil { + return err + } + return runPolicyAdvisorForService(serviceId, o) + } + + if err := outputHeader(o); err != nil { + return err + } + return runPolicyAdvisorForServices(o) +} + +func outputHeader(o *policyAdvisorOptions) error { + if o.quiet { + return nil + } + _, err := fmt.Fprintf(o.Out, "\n"+ + "Policy General Guidelines\n"+ + " In order for an identity to dial or bind a service, the following must be true:\n"+ + " - The identity must have access to the service via a service policy of the correct type (dial or bind)\n"+ + " - The identity must have acces to at least one on-line edge router via an edge router policy\n"+ + " - The service must have access to at least one on-line edge router via a service edge router policy\n"+ + " - There must be at least one on-line edge router that both the identity and service have access to.\n"+ + "\n"+ + "Policy Advisor Output Guide:\n"+ + " STATUS = The status of the identity -> service reachability. Will be OKAY or ERROR. \n"+ + " ID = identity name\n"+ + " ID ROUTERS = number of routers accessible to the identity via edge router policies.\n"+ + " - See edge router polices for an identity: ziti edge controller list identity edge-router-policies \n"+ + " SVC = service name\n"+ + " SVC ROUTERS = number of routers accessible to the service via service edge router policies.\n"+ + " - See service edge router policies for a service with: ziti edge controller list service service-edge-router-policies \n"+ + " ONLINE COMMON ROUTERS = number of routers the identity and service have in common which are online.\n"+ + " COMMON ROUTERS = number of routers (online or offline) the identity and service have in common.\n"+ + " DIAL_OK = indicates if the identity has permission to dial the service.\n"+ + " - See service polices for a service : ziti edge controller list service service-policies \n"+ + " - See service polices for an identity: ziti edge controller list identity service-policies \n"+ + " BIND_OK = indicates if the identity has permission to bind the service.\n"+ + " ERROR_LIST = if the status is ERROR, error details will be listed on the following lines\n"+ + "\n"+ + "Output format: STATUS: ID (ID ROUTERS) -> SVC (SVC ROUTERS) Common Routers: (ONLINE COMMON ROUTERS/COMMON ROUTERS) Dial: DIAL_OK Bind: BIND_OK. ERROR_LIST\n"+ + "-------------------------------------------------------------------------------\n") + return err +} + +func runPolicyAdvisorForIdentities(o *policyAdvisorOptions) error { + skip := 0 + done := false + for !done { + filter := fmt.Sprintf(`true skip %v limit 2`, skip) + children, err := filterEntitiesOfType("identities", filter, false, o.Out) + if err != nil { + panic(err) + } + + for _, child := range children { + identityId, _ := child.S("id").Data().(string) + if err := runPolicyAdvisorForIdentity(identityId, o); err != nil { + panic(err) + } + } + skip += len(children) + if len(children) == 0 { + done = true + } + } + + if skip == 0 { + _, err := fmt.Fprintln(o.Out, "No identities found") + return err + } + + return nil +} + +func runPolicyAdvisorForServices(o *policyAdvisorOptions) error { + skip := 0 + done := false + for !done { + filter := fmt.Sprintf(`true skip %v limit 2`, skip) + children, err := filterEntitiesOfType("services", filter, false, o.Out) + if err != nil { + panic(err) + } + + for _, child := range children { + serviceId, _ := child.S("id").Data().(string) + if err := runPolicyAdvisorForService(serviceId, o); err != nil { + panic(err) + } + } + skip += len(children) + if len(children) == 0 { + done = true + } + } + + if skip == 0 { + _, err := fmt.Fprintln(o.Out, "No services found") + return err + } + + return nil +} + +func runPolicyAdvisorForIdentity(identityId string, o *policyAdvisorOptions) error { + skip := 0 + done := false + for !done { + filter := "true limit 2" + filter = fmt.Sprintf(`true skip %v limit 2`, skip) + children, err := filterSubEntitiesOfType("identities", "services", identityId, filter, &o.commonOptions) + if err != nil { + panic(err) + } + + for _, child := range children { + serviceId, _ := child.S("id").Data().(string) + if err := runPolicyAdvisorForIdentityAndService(identityId, serviceId, o); err != nil { + panic(err) + } + } + skip += len(children) + if len(children) == 0 { + done = true + } + } + + if skip == 0 { + identityName, err := mapIdToName("identities", identityId) + if err != nil { + return err + } + _, err = fmt.Fprintf(o.Out, "ERROR: %v %v\n\n", identityName, "\n - Identity does not have access to any services. Adjust service policies.") + return err + } + + return nil +} + +func runPolicyAdvisorForService(serviceId string, o *policyAdvisorOptions) error { + skip := 0 + done := false + for !done { + filter := "true limit 2" + filter = fmt.Sprintf(`true skip %v limit 2`, skip) + children, err := filterSubEntitiesOfType("services", "identities", serviceId, filter, &o.commonOptions) + if err != nil { + panic(err) + } + + for _, child := range children { + identityId, _ := child.S("id").Data().(string) + if err := runPolicyAdvisorForIdentityAndService(identityId, serviceId, o); err != nil { + panic(err) + } + } + skip += len(children) + if len(children) == 0 { + done = true + } + } + + if skip == 0 { + serviceName, err := mapIdToName("services", serviceId) + if err != nil { + return err + } + _, err = fmt.Fprintf(o.Out, "ERROR: %v %v\n\n", serviceName, "\n - Service is not accessible by any identities. Adjust service policies.") + return err + } + + return nil +} + +func runPolicyAdvisorForIdentityAndService(identityId, serviceId string, o *policyAdvisorOptions) error { + result, err := util.EdgeControllerList("identities/"+identityId+"/policy-advice/"+serviceId, nil, o.OutputJSONResponse, o.Out) + if err != nil || o.OutputJSONResponse { + return err + } + + identityName, _ := result.S("data", "identity", "name").Data().(string) + serviceName, _ := result.S("data", "service", "name").Data().(string) + isBindAllowed, _ := result.S("data", "isBindAllowed").Data().(bool) + isDialAllowed, _ := result.S("data", "isDialAllowed").Data().(bool) + identityRouterCount, _ := result.S("data", "identityRouterCount").Data().(float64) + serviceRouterCount, _ := result.S("data", "serviceRouterCount").Data().(float64) + + commonRouters, err := result.S("data", "commonRouters").Children() + if err != nil && err != gabs.ErrNotObjOrArray { + return err + } + + commonCount := len(commonRouters) + onlineCount := 0 + for _, commonRouter := range commonRouters { + isOnline := commonRouter.S("isOnline").Data().(bool) + if isOnline { + onlineCount++ + } + } + + status := "OKAY " + detail := "" + if !isBindAllowed && !isDialAllowed { + status = "ERROR" + detail += "\n - No access to service. Adjust service policies." + } + + if identityRouterCount < 1 { + status = "ERROR" + detail += "\n - Identity has no edge routers assigned. Adjust edge router policies." + } + + if serviceRouterCount < 1 { + status = "ERROR" + detail += "\n - Service has no edge routers assigned. Adjust service edge router policies." + } + + if identityRouterCount > 0 && serviceRouterCount > 0 { + if commonCount < 1 { + status = "ERROR" + detail += "\n - Identity and services have no edge routers in common. Adjust edge router policies and/or service edge router policies." + } else if onlineCount < 1 { + status = "ERROR" + detail += "\n - Common edge routers are all off-line. Bring routers back on-line or adjust edge router policies and/or service edge router policies to increase common router pool." + } + } + + dialStatus := "Y" + if !isDialAllowed { + dialStatus = "N" + } + + bindStatus := "Y" + if !isBindAllowed { + bindStatus = "N" + } + + _, err = fmt.Fprintf(o.Out, "%v: %v (%v) -> %v (%v) Common Routers: (%v/%v) Dial: %v Bind: %v %v\n\n", + status, identityName, identityRouterCount, serviceName, serviceRouterCount, onlineCount, commonCount, dialStatus, bindStatus, detail) + + return err +} diff --git a/ziti/cmd/ziti/cmd/edge_controller/root.go b/ziti/cmd/ziti/cmd/edge_controller/root.go index bb63cd951..8ebb474f1 100644 --- a/ziti/cmd/ziti/cmd/edge_controller/root.go +++ b/ziti/cmd/ziti/cmd/edge_controller/root.go @@ -48,6 +48,7 @@ func newCmdEdgeController(f cmdutil.Factory, out io.Writer, errOut io.Writer) *c cmd.AddCommand(newListCmd(f, out, errOut)) cmd.AddCommand(newUpdateCmd(f, out, errOut)) cmd.AddCommand(newVersionCmd(f, out, errOut)) + cmd.AddCommand(newPolicyAdivsorCmd(f, out, errOut)) return cmd }