Skip to content

Commit

Permalink
feat(kuma-cp) consolidate tokens logic to support expiration, rotatio…
Browse files Browse the repository at this point in the history
…n, revocation and RSA256 (#3376)

Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
  • Loading branch information
jakubdyszkiewicz committed Dec 2, 2021
1 parent 4f43691 commit cc23532
Show file tree
Hide file tree
Showing 66 changed files with 1,470 additions and 1,048 deletions.
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
}
3 changes: 2 additions & 1 deletion app/kumactl/cmd/generate/generate_zoneingress_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 @@ -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
16 changes: 7 additions & 9 deletions app/kumactl/pkg/tokens/client_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package tokens_test

import (
"context"
"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 +25,10 @@ type staticTokenIssuer struct {

var _ issuer.DataplaneTokenIssuer = &staticTokenIssuer{}

func (s *staticTokenIssuer) Generate(identity issuer.DataplaneIdentity) (issuer.Token, error) {
func (s *staticTokenIssuer) Generate(ctx context.Context, 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 +53,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 +84,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
15 changes: 6 additions & 9 deletions app/kumactl/pkg/tokens/zoneingress_client_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package tokens_test

import (
"context"
"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 +24,10 @@ type zoneIngressStaticTokenIssuer struct {

var _ zoneingress.TokenIssuer = &zoneIngressStaticTokenIssuer{}

func (z *zoneIngressStaticTokenIssuer) Generate(identity zoneingress.Identity) (zoneingress.Token, error) {
func (z *zoneIngressStaticTokenIssuer) Generate(ctx context.Context, 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 +52,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 +83,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
Loading

0 comments on commit cc23532

Please sign in to comment.