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

feat(kuma-cp) consolidate tokens logic to support expiration, rotation, revocation and RSA256 #3376

Merged
merged 4 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/kumactl/cmd/completion/testdata/bash.golden
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,10 @@ _kumactl_generate_dataplane-token()
two_word_flags+=("--tag")
local_nonpersistent_flags+=("--tag")
local_nonpersistent_flags+=("--tag=")
flags+=("--valid-for=")
two_word_flags+=("--valid-for")
local_nonpersistent_flags+=("--valid-for")
local_nonpersistent_flags+=("--valid-for=")
flags+=("--config-file=")
two_word_flags+=("--config-file")
flags+=("--log-level=")
Expand Down Expand Up @@ -968,6 +972,10 @@ _kumactl_generate_zone-ingress-token()
flags_with_completion=()
flags_completion=()

flags+=("--valid-for=")
two_word_flags+=("--valid-for")
local_nonpersistent_flags+=("--valid-for")
local_nonpersistent_flags+=("--valid-for=")
flags+=("--zone=")
two_word_flags+=("--zone")
local_nonpersistent_flags+=("--zone")
Expand Down
6 changes: 4 additions & 2 deletions app/kumactl/cmd/generate/context/context.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package context

import "github.com/kumahq/kuma/pkg/tokens/builtin/issuer"
import (
"github.com/kumahq/kuma/pkg/core/tokens"
)

type GenerateContext struct {
NewSigningKey func() ([]byte, error)
}

func DefaultGenerateContext() GenerateContext {
return GenerateContext{
NewSigningKey: issuer.NewSigningKey,
NewSigningKey: tokens.NewSigningKey,
}
}
14 changes: 9 additions & 5 deletions app/kumactl/cmd/generate/generate_dataplane_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package generate

import (
"strings"
"time"

"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand All @@ -16,6 +17,7 @@ type generateDataplaneTokenContext struct {
name string
proxyType string
tags map[string]string
validFor time.Duration
}
}

Expand All @@ -27,16 +29,16 @@ func NewGenerateDataplaneTokenCmd(pctx *kumactl_cmd.RootContext) *cobra.Command
Long: `Generate Dataplane Token that is used to prove Dataplane identity.`,
Example: `
Generate token bound by name and mesh
$ kumactl generate dataplane-token --mesh demo --name demo-01
$ kumactl generate dataplane-token --mesh demo --name demo-01 --valid-for 24h
Generate token bound by mesh
$ kumactl generate dataplane-token --mesh demo
$ kumactl generate dataplane-token --mesh demo --valid-for 24h
Generate Ingress token
$ kumactl generate dataplane-token --type ingress
$ kumactl generate dataplane-token --type ingress --valid-for 24h
Generate token bound by tag
$ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api
$ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api --valid-for 24h
`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
Expand All @@ -50,7 +52,7 @@ $ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api
tags[k] = strings.Split(v, ",")
}
name := ctx.args.name
token, err := client.Generate(name, pctx.Args.Mesh, tags, ctx.args.proxyType)
token, err := client.Generate(name, pctx.Args.Mesh, tags, ctx.args.proxyType, ctx.args.validFor)
if err != nil {
return errors.Wrap(err, "failed to generate a dataplane token")
}
Expand All @@ -63,5 +65,7 @@ $ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api
_ = cmd.Flags().MarkDeprecated("type", "please use --proxy-type instead")
cmd.Flags().StringVar(&ctx.args.proxyType, "proxy-type", "", `type of the Dataplane ("dataplane", "ingress")`)
cmd.Flags().StringToStringVar(&ctx.args.tags, "tag", nil, "required tag values for dataplane (split values by comma to provide multiple values)")
// Backwards compatibility with 1.3.x. Right now we pick 10 years as default, but in the future this should be required argument without default.
cmd.Flags().DurationVar(&ctx.args.validFor, "valid-for", 24*time.Hour*365*10, `how long the token will be valid (for example "24h")`)
return cmd
}
3 changes: 2 additions & 1 deletion app/kumactl/cmd/generate/generate_dataplane_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
Expand All @@ -26,7 +27,7 @@ type staticDataplaneTokenGenerator struct {

var _ tokens.DataplaneTokenClient = &staticDataplaneTokenGenerator{}

func (s *staticDataplaneTokenGenerator) Generate(name string, mesh string, tags map[string][]string, dpType string) (string, error) {
func (s *staticDataplaneTokenGenerator) Generate(name string, mesh string, tags map[string][]string, dpType string, validFor time.Duration) (string, error) {
if s.err != nil {
return "", s.err
}
Expand Down
11 changes: 8 additions & 3 deletions app/kumactl/cmd/generate/generate_zoneingress_token.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package generate

import (
"time"

"github.com/pkg/errors"
"github.com/spf13/cobra"

Expand All @@ -11,7 +13,8 @@ type generateZoneIngressTokenContext struct {
*kumactl_cmd.RootContext

args struct {
zone string
zone string
validFor time.Duration
}
}

Expand All @@ -23,7 +26,7 @@ func NewGenerateZoneIngressTokenCmd(pctx *kumactl_cmd.RootContext) *cobra.Comman
Long: `Generate Zone Ingress Token that is used to prove Zone Ingress identity.`,
Example: `
Generate token bound by zone
$ kumactl generate zone-ingress-token --zone zone-1
$ kumactl generate zone-ingress-token --zone zone-1 --valid-for 30d
`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
Expand All @@ -32,7 +35,7 @@ $ kumactl generate zone-ingress-token --zone zone-1
return errors.Wrap(err, "failed to create zone ingress token client")
}

token, err := client.Generate(ctx.args.zone)
token, err := client.Generate(ctx.args.zone, ctx.args.validFor)
if err != nil {
return errors.Wrap(err, "failed to generate a zone ingress token")
}
Expand All @@ -41,5 +44,7 @@ $ kumactl generate zone-ingress-token --zone zone-1
},
}
cmd.Flags().StringVar(&ctx.args.zone, "zone", "", "name of the zone where ingress resides")
// Backwards compatibility with 1.3.x. Right now we pick 10 years as default, but in the future this should be required argument without default.
cmd.Flags().DurationVar(&ctx.args.validFor, "valid-for", 24*time.Hour*365*10, `how long the token will be valid (for example "24h")`)
return cmd
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
Expand All @@ -25,7 +26,7 @@ type staticZoneIngressTokenGenerator struct {

var _ tokens.ZoneIngressTokenClient = &staticZoneIngressTokenGenerator{}

func (s *staticZoneIngressTokenGenerator) Generate(zone string) (string, error) {
func (s *staticZoneIngressTokenGenerator) Generate(zone string, validFor time.Duration) (string, error) {
if s.err != nil {
return "", s.err
}
Expand Down
14 changes: 8 additions & 6 deletions app/kumactl/pkg/tokens/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"io"
"net/http"
"time"

"github.com/pkg/errors"

Expand All @@ -20,7 +21,7 @@ func NewDataplaneTokenClient(client util_http.Client) DataplaneTokenClient {
}

type DataplaneTokenClient interface {
Generate(name string, mesh string, tags map[string][]string, dpType string) (string, error)
Generate(name string, mesh string, tags map[string][]string, dpType string, validFor time.Duration) (string, error)
}

type httpDataplaneTokenClient struct {
Expand All @@ -29,12 +30,13 @@ type httpDataplaneTokenClient struct {

var _ DataplaneTokenClient = &httpDataplaneTokenClient{}

func (h *httpDataplaneTokenClient) Generate(name string, mesh string, tags map[string][]string, dpType string) (string, error) {
func (h *httpDataplaneTokenClient) Generate(name string, mesh string, tags map[string][]string, dpType string, validFor time.Duration) (string, error) {
tokenReq := &types.DataplaneTokenRequest{
Name: name,
Mesh: mesh,
Tags: tags,
Type: dpType,
Name: name,
Mesh: mesh,
Tags: tags,
Type: dpType,
ValidFor: validFor.String(),
}
reqBytes, err := json.Marshal(tokenReq)
if err != nil {
Expand Down
15 changes: 6 additions & 9 deletions app/kumactl/pkg/tokens/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"time"

"github.com/emicklei/go-restful"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/pkg/errors"

kumactl_client "github.com/kumahq/kuma/app/kumactl/pkg/client"
"github.com/kumahq/kuma/app/kumactl/pkg/tokens"
config_kumactl "github.com/kumahq/kuma/pkg/config/app/kumactl/v1alpha1"
core_tokens "github.com/kumahq/kuma/pkg/core/tokens"
"github.com/kumahq/kuma/pkg/tokens/builtin/access"
"github.com/kumahq/kuma/pkg/tokens/builtin/issuer"
tokens_server "github.com/kumahq/kuma/pkg/tokens/builtin/server"
Expand All @@ -23,14 +24,10 @@ type staticTokenIssuer struct {

var _ issuer.DataplaneTokenIssuer = &staticTokenIssuer{}

func (s *staticTokenIssuer) Generate(identity issuer.DataplaneIdentity) (issuer.Token, error) {
func (s *staticTokenIssuer) Generate(identity issuer.DataplaneIdentity, validFor time.Duration) (core_tokens.Token, error) {
return fmt.Sprintf("token-for-%s-%s", identity.Name, identity.Mesh), nil
}

func (s *staticTokenIssuer) Validate(token issuer.Token, meshName string) (issuer.DataplaneIdentity, error) {
return issuer.DataplaneIdentity{}, errors.New("not implemented")
}

var _ = Describe("Tokens Client", func() {

var server *httptest.Server
Expand All @@ -55,12 +52,12 @@ var _ = Describe("Tokens Client", func() {

// wait for server
Eventually(func() error {
_, err := client.Generate("example", "default", nil, "dataplane")
_, err := client.Generate("example", "default", nil, "dataplane", 24*time.Hour)
return err
}, "5s", "100ms").ShouldNot(HaveOccurred())

// when
token, err := client.Generate("example", "default", nil, "dataplane")
token, err := client.Generate("example", "default", nil, "dataplane", 24*time.Hour)

// then
Expect(err).ToNot(HaveOccurred())
Expand All @@ -86,7 +83,7 @@ var _ = Describe("Tokens Client", func() {
Expect(err).ToNot(HaveOccurred())

// when
_, err = client.Generate("example", "default", nil, "dataplane")
_, err = client.Generate("example", "default", nil, "dataplane", 24*time.Hour)

// then
Expect(err).To(MatchError("(500): Internal Server Error"))
Expand Down
8 changes: 5 additions & 3 deletions app/kumactl/pkg/tokens/zoneingress_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"io"
"net/http"
"time"

"github.com/pkg/errors"

Expand All @@ -20,7 +21,7 @@ func NewZoneIngressTokenClient(client util_http.Client) ZoneIngressTokenClient {
}

type ZoneIngressTokenClient interface {
Generate(zone string) (string, error)
Generate(zone string, validFor time.Duration) (string, error)
}

type httpZoneIngressTokenClient struct {
Expand All @@ -29,9 +30,10 @@ type httpZoneIngressTokenClient struct {

var _ ZoneIngressTokenClient = &httpZoneIngressTokenClient{}

func (h *httpZoneIngressTokenClient) Generate(zone string) (string, error) {
func (h *httpZoneIngressTokenClient) Generate(zone string, validFor time.Duration) (string, error) {
tokenReq := &types.ZoneIngressTokenRequest{
Zone: zone,
Zone: zone,
ValidFor: validFor.String(),
}
reqBytes, err := json.Marshal(tokenReq)
if err != nil {
Expand Down
14 changes: 5 additions & 9 deletions app/kumactl/pkg/tokens/zoneingress_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"time"

"github.com/emicklei/go-restful"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/pkg/errors"

kumactl_client "github.com/kumahq/kuma/app/kumactl/pkg/client"
"github.com/kumahq/kuma/app/kumactl/pkg/tokens"
Expand All @@ -23,14 +23,10 @@ type zoneIngressStaticTokenIssuer struct {

var _ zoneingress.TokenIssuer = &zoneIngressStaticTokenIssuer{}

func (z *zoneIngressStaticTokenIssuer) Generate(identity zoneingress.Identity) (zoneingress.Token, error) {
func (z *zoneIngressStaticTokenIssuer) Generate(identity zoneingress.Identity, validFor time.Duration) (zoneingress.Token, error) {
return fmt.Sprintf("token-for-%s", identity.Zone), nil
}

func (z *zoneIngressStaticTokenIssuer) Validate(token zoneingress.Token) (zoneingress.Identity, error) {
return zoneingress.Identity{}, errors.New("not implemented")
}

var _ = Describe("Zone Ingress Tokens Client", func() {

var server *httptest.Server
Expand All @@ -55,12 +51,12 @@ var _ = Describe("Zone Ingress Tokens Client", func() {

// wait for server
Eventually(func() error {
_, err := client.Generate("my-zone-1")
_, err := client.Generate("my-zone-1", 24*time.Hour)
return err
}, "5s", "100ms").ShouldNot(HaveOccurred())

// when
token, err := client.Generate("my-zone-1")
token, err := client.Generate("my-zone-1", 24*time.Hour)

// then
Expect(err).ToNot(HaveOccurred())
Expand All @@ -86,7 +82,7 @@ var _ = Describe("Zone Ingress Tokens Client", func() {
Expect(err).ToNot(HaveOccurred())

// when
_, err = client.Generate("my-zone-2")
_, err = client.Generate("my-zone-2", 24*time.Hour)

// then
Expect(err).To(MatchError("(500): Internal Server Error"))
Expand Down
9 changes: 5 additions & 4 deletions docs/cmd/kumactl/kumactl_generate_dataplane-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ kumactl generate dataplane-token [flags]
```

Generate token bound by name and mesh
$ kumactl generate dataplane-token --mesh demo --name demo-01
$ kumactl generate dataplane-token --mesh demo --name demo-01 --valid-for 24h

Generate token bound by mesh
$ kumactl generate dataplane-token --mesh demo
$ kumactl generate dataplane-token --mesh demo --valid-for 24h

Generate Ingress token
$ kumactl generate dataplane-token --type ingress
$ kumactl generate dataplane-token --type ingress --valid-for 24h

Generate token bound by tag
$ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api
$ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api --valid-for 24h

```

Expand All @@ -35,6 +35,7 @@ $ kumactl generate dataplane-token --mesh demo --tag kuma.io/service=web,web-api
--name string name of the Dataplane
--proxy-type string type of the Dataplane ("dataplane", "ingress")
--tag stringToString required tag values for dataplane (split values by comma to provide multiple values) (default [])
--valid-for duration how long the token will be valid (for example "24h") (default 87600h0m0s)
```

### Options inherited from parent commands
Expand Down
7 changes: 4 additions & 3 deletions docs/cmd/kumactl/kumactl_generate_zone-ingress-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ kumactl generate zone-ingress-token [flags]
```

Generate token bound by zone
$ kumactl generate zone-ingress-token --zone zone-1
$ kumactl generate zone-ingress-token --zone zone-1 --valid-for 30d

```

### Options

```
-h, --help help for zone-ingress-token
--zone string name of the zone where ingress resides
-h, --help help for zone-ingress-token
--valid-for duration how long the token will be valid (for example "24h") (default 87600h0m0s)
--zone string name of the zone where ingress resides
```

### Options inherited from parent commands
Expand Down
Loading