Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updates change log and CLI ca support #834

Merged
merged 1 commit into from Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 96 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,99 @@
# Release 0.26.8

## What's New

- Edge
- Bug Fixes
- Ziti CLI
- `ziti edge create|update ca` now supports `externalIdClaim`
- Improved List CAs
- Identity
- Automatic File Reloads

## Edge
### Bug Fixes

* [Issue 1176](https://github.com/openziti/edge/issues/1176): Patching CA `externalIdClaim` Does Not Work

## Ziti CLI

### `ziti edge create|update ca` now support `externalIdClaim

Identities now have a field named `externalId` that can be used with 3rd Party CAs in addition to the existing
External JWT Signer support. 3rd Party CAs now support the following optional fields:

- `externalIdClaim.index` - if multiple externalId claims are located, the index will be used to select one, default 0
- `externalIdClaim.location` - extracts values from one of the following locations on a x509 certificate: `SAN_URI`, `SAN_EMAIL`, `COMMON_NAME`
- `externalIdClaim.matcher` - matches values in one of the following ways `PREFIX`, `SUFFIX`, `SCHEME` in conjunction with `matcherCriteria` or select all values via `ALL`
- `externalIdClaim.matcherCriteria` - `matcher` values of `PREFIX`, `SUFFIX`, and `SCHEME` will use `matcherCriteria` as a matching value
- `externalIdClaim.parser`: - supports parsing values from all matched externalIds via `SPLIT` or `NONE`
- `externalIdClaim.parserCriteria` - for a `parser` value of `SPLIT`, `parserCriteria` will be used to split values

When defined the `externalIdClaim` configuration will be used to locate any `externalId`s present in the client
supplied x509 certificate. If an `externalId` is located, it will be used to associate the authentication request
with an identity. If found, authentication is considered successful if not the authentication request fails. If the
client certificate does not contain an `externalId` then identities will be searched for that have a certificate
authenticator that matches the supplied client certificate. Should that fail, the authentication request fails.

This functionality can be used to support SPIFFE provisioned identities. For any specific SPIFFE ID, assign it to an
identity's `externalId` and then use the following `externalIdClaim` configurations.

#### CA Create/Update REST API
```json
{
...
"externalIdClaim": {
"location": "SAN_URI",
"index": 0,
"matcher": "SCHEME",
"matcherCriteria": "spiffe",
"parser": "NONE",
"parserCriteria": ""
}
}
```
#### Ziti CLI

```
ziti edge create ca myCa ca.pem -l SAN_URI -m SCHEME -x spiffe -p "NONE"
```

```
ziti edge update ca myCa -l SAN_URI -m SCHEME -x spiffe -p "NONE"
```

### Improved List CAs Output

The output for listing CAs in non-JSON format has been improved.

Example:

```text
╭────────────────────────┬─────────┬────────┬────────────┬─────────────┬─────────────────────────────────────────────────────────────────╮
│ ID │ NAME │ FLAGS │ TOKEN │ FINGERPRINT │ CONFIGURATION │
├────────────────────────┼─────────┼────────┼────────────┼─────────────┼─────────────────┬──────────────────────┬────────────────────────┤
│ 1tu6CbXT18Dd9rybjCW5eX │ 2 │ [AOE] │ KaPxRiKbk │ - │ AutoCA │ Identity Name Format │ [caName]-[commonName] │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Identity Roles │ a,b,c │
│ │ │ │ │ ├─────────────────┼──────────────────────┼────────────────────────┤
│ │ │ │ │ │ ExternalIdClaim │ Index │ 2 │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Location │ SAN_URI │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Matcher │ ALL │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Matcher Criteria │ │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Parser │ NONE │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Parser Criteria │ │
├────────────────────────┼─────────┼────────┼────────────┼─────────────┼─────────────────┼──────────────────────┼────────────────────────┤
│ 7AGp9vUttJHKA1JWujNtpR │ test-ca │ [VAOE] │ - │ 315e...ba │ AutoCA │ Identity Name Format │ [caName]-[commonName] │
│ │ │ │ │ │ ├──────────────────────┼────────────────────────┤
│ │ │ │ │ │ │ Identity Roles │ three, two,one │
╰────────────────────────┴─────────┴────────┴────────────┴─────────────┴─────────────────┴──────────────────────┴────────────────────────╯
```

# Release 0.26.7

## What's New
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Expand Up @@ -24,13 +24,13 @@ require (
github.com/michaelquigley/pfxlog v0.6.9
github.com/openziti/agent v1.0.3
github.com/openziti/channel v1.0.2
github.com/openziti/edge v0.22.91
github.com/openziti/fabric v0.19.67
github.com/openziti/edge v0.22.95
github.com/openziti/fabric v0.19.69
github.com/openziti/foundation/v2 v2.0.4
github.com/openziti/identity v1.0.11
github.com/openziti/metrics v1.0.7
github.com/openziti/sdk-golang v0.16.119
github.com/openziti/storage v0.1.20
github.com/openziti/storage v0.1.21
github.com/openziti/transport/v2 v2.0.28
github.com/openziti/xweb/v2 v2.0.2
github.com/openziti/ziti-db-explorer v1.1.1
Expand Down Expand Up @@ -161,7 +161,7 @@ require (
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 // indirect
golang.org/x/sys v0.0.0-20220913175220-63ea55921009 // indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.7 // indirect
Expand Down
16 changes: 8 additions & 8 deletions go.sum
Expand Up @@ -679,10 +679,10 @@ github.com/openziti/channel v1.0.2 h1:hNnmIHDb3RY7B0wX9TOn+XqObjfoTPWDBNjTa42nvx
github.com/openziti/channel v1.0.2/go.mod h1:vb2IonzG4uLmFj7UTIHTKViI2W8tHE+skFTeynZ+hJE=
github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k=
github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo=
github.com/openziti/edge v0.22.91 h1:/55k3noqvY5CYJlY8ySC17Q2mEcI5/nbj1/6+HS7EA0=
github.com/openziti/edge v0.22.91/go.mod h1:GE3iyHd1VCY7NU10RQaFSTWi+9GrDN84eyarWAIzW7A=
github.com/openziti/fabric v0.19.67 h1:rH2EEwo6y7th0HXdjhkHJeIYq8il6Z3Fu/5Qh2icSZ8=
github.com/openziti/fabric v0.19.67/go.mod h1:xYVUbDJA1NZae+Wpo5Lc1N1XF+cnLnqaYwi+KiEXUMs=
github.com/openziti/edge v0.22.95 h1:24jZlqNNAxazib3qma+SbaC+8Mc7F1XEje+ckvQuBZs=
github.com/openziti/edge v0.22.95/go.mod h1:Fdjjs+eVf3nAuGfZAvlU39a4bi/tJMoBfG+Ylv63BJE=
github.com/openziti/fabric v0.19.69 h1:vCJPmANIyiq/kUaVx9CU+RljnJIpvcJaYM8fv1kiQkY=
github.com/openziti/fabric v0.19.69/go.mod h1:XSbL0gbTyhd76yYPNNg/CTJsdaYWUg3Thm8Fs9clpd0=
github.com/openziti/foundation/v2 v2.0.4 h1:QnpbNgRzPTnbu/QIqdNhYJl4nrhxrX7VXiIF5yIqQhc=
github.com/openziti/foundation/v2 v2.0.4/go.mod h1:L75kwCC5WTUPqxuAd3G+WMBompaElMb/nYlJjR1sJ9Q=
github.com/openziti/identity v1.0.11 h1:66tdzw5gillevcTNXZGbLxB03d/l2KTGbS4mrDJg7WY=
Expand All @@ -693,8 +693,8 @@ github.com/openziti/metrics v1.0.7 h1:gI1Vk2HIPUwIgS42bZJ0MZx+ATfIU1Pnv5troch8R5
github.com/openziti/metrics v1.0.7/go.mod h1:x+2e9YQyZjf94KFWW3rr9hx+agfk50kP53vMP/6eMzo=
github.com/openziti/sdk-golang v0.16.119 h1:B51X/3/qpSNYJIF9D903nvPVR0suGw/fZvw6aNzF/bo=
github.com/openziti/sdk-golang v0.16.119/go.mod h1:ln61i+bB/Qy8IsjDzu8iw8V//PFefCY9UuhCsz60fPk=
github.com/openziti/storage v0.1.20 h1:6wYIwtNeymni4bVSznelVQ4WIkSPzYjh6ybIO704QVY=
github.com/openziti/storage v0.1.20/go.mod h1:onJ7mLnnB2nfKdNCJHZlVRnPZSSPUJvuu3gzZ8vR2Mo=
github.com/openziti/storage v0.1.21 h1:m8ny8AuCqjZQRpiHUhQlmZjUGAW1LCRjrPA93WQsjP0=
github.com/openziti/storage v0.1.21/go.mod h1:onJ7mLnnB2nfKdNCJHZlVRnPZSSPUJvuu3gzZ8vR2Mo=
github.com/openziti/transport/v2 v2.0.28 h1:ptfqproXYToJR2QncsbdlRjHh7OGBlo2Jgmk+dFpNsc=
github.com/openziti/transport/v2 v2.0.28/go.mod h1:I0JnNq899+rwArGlSq9sVqCCD5c805FUv0VQgFhWNYI=
github.com/openziti/x509-claims v1.0.2 h1:PSv/xRfejIAcPc16A902k08rSBs3R8bjtL4qq6WEwCI=
Expand Down Expand Up @@ -1193,8 +1193,8 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220913175220-63ea55921009 h1:PuvuRMeLWqsf/ZdT1UUZz0syhioyv1mzuFZsXs4fvhw=
golang.org/x/sys v0.0.0-20220913175220-63ea55921009/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand Down
128 changes: 94 additions & 34 deletions ziti/cmd/ziti/cmd/edge/create_ca.go
Expand Up @@ -18,26 +18,22 @@ package edge

import (
"fmt"
"github.com/Jeffail/gabs"
"github.com/openziti/edge/rest_management_api_client/certificate_authority"
"github.com/openziti/edge/rest_model"
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
"github.com/openziti/ziti/ziti/cmd/ziti/util"
"github.com/spf13/cobra"
"io"
"io/ioutil"
"os"
)

type createCaOptions struct {
api.Options
tags map[string]string
name string
caPath string
caPemBytes []byte
autoCaEnrollment bool
ottCaEnrollment bool
authEnabled bool
identityRoles []string
identityNameFormat string
Ca rest_model.CaCreate
TagsFromFlags map[string]string
IdentityRolesFromFlags []string
}

// newCreateCaCmd creates the 'edge controller create ca local' command for the given entity type
Expand All @@ -49,7 +45,27 @@ func newCreateCaCmd(out io.Writer, errOut io.Writer) *cobra.Command {
Err: errOut,
},
},
tags: make(map[string]string),
Ca: rest_model.CaCreate{
CertPem: S(""),
ExternalIDClaim: &rest_model.ExternalIDClaim{
Index: I64(0),
Location: S(""),
Matcher: S(""),
MatcherCriteria: S(""),
Parser: S(""),
ParserCriteria: S(""),
},
IdentityNameFormat: "",
IdentityRoles: []string{},
IsAuthEnabled: B(false),
IsAutoCaEnrollmentEnabled: B(false),
IsOttCaEnrollmentEnabled: B(false),
Name: S(""),
Tags: &rest_model.Tags{
SubTags: map[string]interface{}{},
},
},
TagsFromFlags: map[string]string{},
}

cmd := &cobra.Command{
Expand All @@ -61,11 +77,13 @@ func newCreateCaCmd(out io.Writer, errOut io.Writer) *cobra.Command {
return fmt.Errorf("requires at least %d arg(s), only received %d", 2, len(args))
}

options.name = args[0]
options.caPath = args[1]
options.Ca.Name = &args[0]

caFile := args[1]

var err error
options.caPemBytes, err = ioutil.ReadFile(options.caPath)
pemBytes, err := os.ReadFile(caFile)

options.Ca.CertPem = S(string(pemBytes))

if err != nil {
return fmt.Errorf("could not read CA certificate file: %s", err)
Expand All @@ -85,30 +103,72 @@ func newCreateCaCmd(out io.Writer, errOut io.Writer) *cobra.Command {

// allow interspersing positional args and flags
cmd.Flags().SetInterspersed(true)
cmd.Flags().StringToStringVarP(&options.tags, "tags", "t", nil, "Add tags to service definition")
cmd.Flags().BoolVarP(&options.authEnabled, "auth", "e", false, "Whether the CA can be used for authentication or not")
cmd.Flags().BoolVarP(&options.ottCaEnrollment, "ottca", "o", false, "Whether the CA can be used for one-time-token CA enrollment")
cmd.Flags().BoolVarP(&options.autoCaEnrollment, "autoca", "u", false, "Whether the CA can be used for auto CA enrollment")
cmd.Flags().StringSliceVarP(&options.identityRoles, "role-attributes", "a", []string{}, "A csv string of role attributes enrolling identities receive")
cmd.Flags().StringVarP(&options.identityNameFormat, "identity-name-format", "f", "", "The naming format to use for identities enrolling via the CA")
cmd.Flags().StringToStringVarP(&options.TagsFromFlags, "tags", "t", nil, "Add tags to service definition")
cmd.Flags().BoolVarP(options.Ca.IsAuthEnabled, "auth", "e", false, "Whether the CA can be used for authentication or not")
cmd.Flags().BoolVarP(options.Ca.IsOttCaEnrollmentEnabled, "ottca", "o", false, "Whether the CA can be used for one-time-token CA enrollment")
cmd.Flags().BoolVarP(options.Ca.IsAutoCaEnrollmentEnabled, "autoca", "u", false, "Whether the CA can be used for auto CA enrollment")
cmd.Flags().StringSliceVarP(&options.IdentityRolesFromFlags, "role-attributes", "a", []string{}, "A csv string of role attributes enrolling identities receive")
cmd.Flags().StringVarP(&options.Ca.IdentityNameFormat, "identity-name-format", "f", "", "The naming format to use for identities enrolling via the CA")

//ExternalIdClaim
cmd.Flags().Int64VarP(options.Ca.ExternalIDClaim.Index, "index", "d", 0, "the index to use if multiple external ids are found, default 0")
cmd.Flags().StringVarP(options.Ca.ExternalIDClaim.Location, "location", "l", "", "the location to search for external ids")
cmd.Flags().StringVarP(options.Ca.ExternalIDClaim.Matcher, "matcher", "m", "", "the matcher to use at the given location")
cmd.Flags().StringVarP(options.Ca.ExternalIDClaim.MatcherCriteria, "matcher-criteria", "x", "", "criteria used with the given matcher")
cmd.Flags().StringVarP(options.Ca.ExternalIDClaim.Parser, "parser", "p", "", "the parser to use on found external ids")
cmd.Flags().StringVarP(options.Ca.ExternalIDClaim.ParserCriteria, "parser-criteria", "z", "", "criteria used with the given parser")

options.AddCommonFlags(cmd)

return cmd
}

func S(s string) *string {
return &s
}

func B(b bool) *bool {
return &b
}

func I64(i int64) *int64 {
return &i
}

func runCreateCa(options *createCaOptions) (err error) {
data := gabs.New()
api.SetJSONValue(data, options.name, "name")
api.SetJSONValue(data, options.autoCaEnrollment, "isAutoCaEnrollmentEnabled")
api.SetJSONValue(data, options.ottCaEnrollment, "isOttCaEnrollmentEnabled")
api.SetJSONValue(data, options.authEnabled, "isAuthEnabled")
api.SetJSONValue(data, string(options.caPemBytes), "certPem")
api.SetJSONValue(data, options.identityRoles, "identityRoles")

if options.Cmd.Flag("identity-name-format").Changed {
api.SetJSONValue(data, options.identityNameFormat, "identityNameFormat")
managementClient, err := util.NewEdgeManagementClient(options)

if err != nil {
return err
}

params := certificate_authority.NewCreateCaParams()
params.Ca = &options.Ca

for _, attr := range options.IdentityRolesFromFlags {
params.Ca.IdentityRoles = append(params.Ca.IdentityRoles, attr)
}

for k, v := range options.TagsFromFlags {
params.Ca.Tags.SubTags[k] = v
}

//clear external id claims if location is not set
if params.Ca.ExternalIDClaim.Location == nil || *params.Ca.ExternalIDClaim.Location == "" {
params.Ca.ExternalIDClaim = nil
}

resp, err := managementClient.CertificateAuthority.CreateCa(params, nil)

if err != nil {
return util.WrapIfApiError(err)
}

checkId := resp.GetPayload().Data.ID

if _, err = fmt.Fprintf(options.Out, "%v\n", checkId); err != nil {
panic(err)
}

result, err := CreateEntityOfType("cas", data.String(), &options.Options)
return options.LogCreateResult("ca", result, err)
return err
}