diff --git a/CHANGELOG.md b/CHANGELOG.md index 1405e7e25..ccdd6a86d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,190 @@ # Release 0.18.5 +## What's New + * Update go-openapi libraries * xgress_edge refactor, should fix 'failed to dipsatch to fabric' errors * Update `ziti use` command to work with main branch +* MFA Support + + +## MFA Support + +Endpoint MFA is available that is based on RFC 4226 (HOTP: An HMAC-Based One-Time Password Algorithm) +and RFC 6238 (TOTP: Time-Based One-Time Password Algorithm). These standards are compatible with standard "Authenticator" +apps such as Google Authenticator and Authy. MFA is suggested to be used in situations where human +operators are involved and additional security is desired. + +### Restricting Service Access + +Services can now have a Posture Check of type MFA that can be created and associated with +a Service Policy. Service Policies that are associated with an MFA Posture Check will restrict +access to services if a client has not enrolled in MFA and passed an MFA check on each login. + +MFA Posture Checks support only the basic Posture Check fields: + +- name - a name for the posture check +- typeId - should be "MFA" +- tags - any tags desired for this object +- roleAttributes - role attributes used to select this object from Service Policies + +Example: +``` +POST /posture-checks +{ + "name": "Any MFA", + "typeId": "MFA", + "roleAttributes": ["mfa"] +} +``` + +### Admin MFA Management + +Admins of the Ziti Edge API can remove MFA from any user. However, they +cannot enroll on behalf of the client. The client will have to initiate +MFA enrollment via their client. + +Endpoints: + +- `DELETE /identities//mfa` - remove MFA from an identity +- `GET /identities` - has a new field `isMfaEnabled` that is true/false based on the identity's MFA enrollment +- `GET /identities//posture-data` - now includes a `sessionPostureData` field which is a map of sessionId -> session posture data (including MFA status) + +Example Posture Data: + +``` +{ + "mac": ["03092ac3bc69", "2b6df1dc52d9"], + "domain": "mycorp.com", + "os": { + ... + }, + processes: [ + ... + ], + sessionPostureData: { + "xV1442s": { + "mfa": { + "passedMfa": true + } + } + } +} + +``` + +### Client MFA Enrollment + +Clients must individually enroll in MFA as the enrollment process includes +exchanging a symmetric key. During MFA enrollment the related MFA endpoints +will return different data and HTTP status codes based upon the state of MFA +enrollment (enrollment not started, enrollment started, enrolled). + +The general MFA enrollment flow is: + +1. Authenticate as the identity via `POST /authenticate` +2. Start MFA enrollment via `POST /current-identity/mfa` +3. Retrieve the MFA provisioning URL or QR code + - `GET /current-identity/mfa` + - `GET /current-identity/mfa/qr-code` +4. Use the provisioning URL or QR code with an authentication app such as Google Authenticator, Authy, etc. +5. Use a current code from the authenticator to `POST /current-identity/mfa/verify` with the code in the `code` field `{"code": "someCode"}` + +#### MFA Endpoints Overview: +This section is an overview for the endpoints. Each endpoint may return errors depending on +in input and MFA status. + +- `GET /current-identity/mfa` - returns the current state of MFA enrollment or 404 Not Found +- `POST /current-identity/mfa` - initiates MFA enrollment or 409 Conflict +- `DELETE /current-identity/mfa` - remove MFA enrollment, requires a valid TOTP or recovery code +- `GET /current-identity/mfa/recovery-codes` - returns the current recovery codes, requires a valid TOTP Code +- `POST /current-identity/mfa/recovery-codes` - regenerates recovery codes, requires a valid TOTP code +- `POST /current-identity/mfa/verify` - allows MFA enrollment to be completed, requires a valid TOTP code +- `GET /current-identity/mfa/qr-code` - returns a QR code for use with QR code scanner, MFA enrollment must be started +- `POST /authenticate/mfa` - allows MFA authentication checks to be completed, requires a valid TOTP or recovery code + + +MFA Enrollment Not Started: + +- `GET /current-identity/mfa` - returns HTTP status 404 +- `POST /current-identity/mfa` - start MFA enrollment, 200 Ok +- `DELETE /current-identity/mfa` - returns 404 Not Found +- `GET /current-identity/mfa/recovery-codes` - returns 404 Not Found +- `POST /current-identity/mfa` - returns 404 Not Found +- `POST /current-identity/mfa/verify` - returns 404 Not Found +- `GET /current-identity/mfa/qr-code` - returns 404 Not Found + +MFA Enrollment Started: +- `GET /current-identity/mfa` - returns the current MFA enrollment and recovery codes +- `POST /current-identity/mfa` - returns 409 Conflict +- `DELETE /current-identity/mfa` - aborts the current enrollment, a blank `code` may be supplied +- `GET /current-identity/mfa/recovery-codes` - returns 404 Not Found +- `POST /current-identity/mfa` - returns HTTP status 409 Conflict +- `POST /current-identity/mfa/verify` - validates the supplied `code` +- `GET /current-identity/mfa/qr-code` - returns a QR code for use with QR code scanner in PNG format + +MFA Completed: +- `GET /current-identity/mfa` - returns the current MFA enrollment, but not recovery codes +- `POST /current-identity/mfa` - returns 409 Conflict +- `DELETE /current-identity/mfa` - removes MFA, a valid TOTP or recovery code must be supplied +- `GET /current-identity/mfa/recovery-codes` - shows the current recovery codes, a valid TOTP code must be supplied +- `POST /current-identity/mfa` - returns HTTP status 409 Conflict +- `POST /current-identity/mfa/verify` - returns HTTP status 409 Conflict +- `GET /current-identity/mfa/qr-code` - returns 404 Not Found + + +### Client MFA Recovery Codes + +Client MFA recovery codes are generated during enrollment and can be regenerated at any +time with a valid TOTP code. Twenty codes are generated and are one time use only. +Generating new codes replaces all existing recovery codes. + +To view: +``` +GET /current-identity/mfa/recovery-codes +{ + "code": "123456" +} +``` + +To Generate new codes: +``` +POST /current-identity/mfa/recovery-codes +{ + "code": "123456" +} +``` + +### Authentication + +During API Session authentication a new `authQuery` field is returned. +This field will indicate if there are any outstanding authentication +Posture Queries that need to be fulfilled before authentication is +considered complete. + +When MFA authentication is required a field will now appear as an +`authQuery` with the following format: + +``` +{ + ... + "token": "c68a187a-f4af-490c-a9dd-a09076511419", + "authQueries": [ + ..., + { + "typeId": "MFA", + "provider": "ZITI", + "httpMethod": "POST", + "httpUrl": "./authenticate/mfa", + "minLength": 4, + "maxLength": 6, + "format": "alphaNumeric" + }, + ... + ] +} +``` + # Release 0.18.4 diff --git a/go.mod b/go.mod index 09801302d..87f18046c 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.3.6 - github.com/openziti/edge v0.17.51 + github.com/openziti/edge v0.17.52 github.com/openziti/fabric v0.15.13 github.com/openziti/foundation v0.15.9 github.com/openziti/sdk-golang v0.15.10 diff --git a/go.sum b/go.sum index 302803e58..ed0da9cbc 100644 --- a/go.sum +++ b/go.sum @@ -96,6 +96,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deepmap/oapi-codegen v1.3.6/go.mod h1:aBozjEveG+33xPiP55Iw/XbVkhtZHEGLq3nxlX0+hfU= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 h1:AqeKSZIG/NIC75MNQlPy/LM3LxfpLwahICJBHwSMFNc= +github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3/go.mod h1:hEfFauPHz7+NnjR/yHJGhrKo1Za+zStgwUETx3yzqgY= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= @@ -518,8 +520,8 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/openziti/edge v0.17.51 h1:jbz0TBv/TdKIJ1LhdeFKsnr6/55ZsL64VYs6jbHrT1k= -github.com/openziti/edge v0.17.51/go.mod h1:ySBvi6wynLctOadIx90MLVNdqJEF88y7obOAipOYEFE= +github.com/openziti/edge v0.17.52 h1:Qd6hgnp0NDyX0b0p1vSvfjZmEgRR2wL2tHg/5giSLRg= +github.com/openziti/edge v0.17.52/go.mod h1:rqHyScpW5UQZRRVEKKVGWgXCfdoLndtPhcsc4cYJrmA= github.com/openziti/fabric v0.15.13 h1:GgS4Sbce6ubkDUtO2oPQFEzh5S9EiAjtMs50NJbuAvo= github.com/openziti/fabric v0.15.13/go.mod h1:B8NeRzN+eIdo2Q4JUCbP0covC5SYqerrxwJsBgCU+A8= github.com/openziti/foundation v0.15.8 h1:BFKDBkgsuXWgCtU7TS3eBPz2gceA057gK6W6IiyUQfM= @@ -605,6 +607,8 @@ github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=