Skip to content

Commit

Permalink
feat(kumactl) provided CA commands (#474)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubdyszkiewicz authored Dec 12, 2019
1 parent 1fb2b56 commit bc7f348
Show file tree
Hide file tree
Showing 34 changed files with 834 additions and 202 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG

## Unreleased

Breaking changes:
* kumactl: `dataplane-token-client-cert` and `dataplane-token-client-key` arguments in `config control-planes add` command
are renamed to `admin-client-cert` and `admin-client-key`.

## [0.3.0]

> Released on 2019/11/18
Expand Down
20 changes: 10 additions & 10 deletions app/kumactl/cmd/config/config_control_planes_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import (

func newConfigControlPlanesAddCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
args := struct {
name string
apiServerURL string
overwrite bool
dataplaneTokenClientCert string
dataplaneTokenClientKey string
name string
apiServerURL string
overwrite bool
adminClientCert string
adminClientKey string
}{}
cmd := &cobra.Command{
Use: "add",
Expand Down Expand Up @@ -45,9 +45,9 @@ func newConfigControlPlanesAddCmd(pctx *kumactl_cmd.RootContext) *cobra.Command
Name: cp.Name,
ControlPlane: cp.Name,
Credentials: &config_proto.Context_Credentials{
DataplaneTokenApi: &config_proto.Context_DataplaneTokenApiCredentials{
ClientCert: args.dataplaneTokenClientCert,
ClientKey: args.dataplaneTokenClientKey,
AdminApi: &config_proto.Context_AdminApiCredentials{
ClientCert: args.adminClientCert,
ClientKey: args.adminClientKey,
},
},
}
Expand All @@ -72,7 +72,7 @@ func newConfigControlPlanesAddCmd(pctx *kumactl_cmd.RootContext) *cobra.Command
cmd.Flags().StringVar(&args.apiServerURL, "address", "", "URL of the Control Plane API Server (required)")
_ = cmd.MarkFlagRequired("address")
cmd.Flags().BoolVar(&args.overwrite, "overwrite", false, "overwrite existing Control Plane with the same reference name")
cmd.Flags().StringVar(&args.dataplaneTokenClientCert, "dataplane-token-client-cert", "", "Path to certificate of a client that is authorized to use Dataplane Token Server")
cmd.Flags().StringVar(&args.dataplaneTokenClientKey, "dataplane-token-client-key", "", "Path to certificate key of a client that is authorized to use Dataplane Token Server")
cmd.Flags().StringVar(&args.adminClientCert, "admin-client-cert", "", "Path to certificate of a client that is authorized to use Admin Server")
cmd.Flags().StringVar(&args.adminClientKey, "admin-client-key", "", "Path to certificate key of a client that is authorized to use Admin Server")
return cmd
}
4 changes: 2 additions & 2 deletions app/kumactl/cmd/config/config_control_planes_add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ var _ = Describe("kumactl config control-planes add", func() {
"config", "control-planes", "add",
"--name", "example",
"--address", fmt.Sprintf("http://localhost:%d", port),
"--dataplane-token-client-cert", "/tmp/client.pem",
"--dataplane-token-client-key", "/tmp/client.key.pem"}
"--admin-client-cert", "/tmp/client.pem",
"--admin-client-key", "/tmp/client.key.pem"}
if given.overwrite {
args = append(args, "--overwrite")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ contexts:
- controlPlane: example
name: example
credentials:
dataplaneTokenApi:
adminApi:
clientCert: /tmp/client.pem
clientKey: /tmp/client.key.pem
controlPlanes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ contexts:
- controlPlane: example
name: example
credentials:
dataplaneTokenApi:
adminApi:
clientCert: /tmp/client.pem
clientKey: /tmp/client.key.pem
controlPlanes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ contexts:
- controlPlane: example
name: example
credentials:
dataplaneTokenApi:
adminApi:
clientCert: /tmp/client.pem
clientKey: /tmp/client.key.pem
controlPlanes:
Expand Down
2 changes: 1 addition & 1 deletion app/kumactl/cmd/generate/generate_dataplane_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var _ = Describe("kumactl generate dataplane-token", func() {
generator = &staticDataplaneTokenGenerator{}
ctx = &kumactl_cmd.RootContext{
Runtime: kumactl_cmd.RootRuntime{
NewDataplaneTokenClient: func(string, *config_kumactl.Context_DataplaneTokenApiCredentials) (tokens.DataplaneTokenClient, error) {
NewDataplaneTokenClient: func(string, *config_kumactl.Context_AdminApiCredentials) (tokens.DataplaneTokenClient, error) {
return generator, nil
},
NewCatalogClient: func(s string) (catalog_client.CatalogClient, error) {
Expand Down
17 changes: 17 additions & 0 deletions app/kumactl/cmd/manage/ca/ca.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ca

import (
kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd"
"github.com/spf13/cobra"
)

func NewCaCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
cmd := &cobra.Command{
Use: "ca",
Short: "Manage certificate authorities",
Long: `Manage certificate authorities.`,
}
// sub-commands
cmd.AddCommand(newProvidedCmd(pctx))
return cmd
}
13 changes: 13 additions & 0 deletions app/kumactl/cmd/manage/ca/ca_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ca_test

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestCa(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "CA Suite")
}
175 changes: 175 additions & 0 deletions app/kumactl/cmd/manage/ca/provided.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package ca

import (
"crypto/sha1"
"crypto/x509"
"encoding/pem"
"fmt"
kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd"
"github.com/Kong/kuma/app/kumactl/pkg/output/printers"
"github.com/Kong/kuma/pkg/core/ca/provided/rest/types"
"github.com/Kong/kuma/pkg/tls"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"io"
"io/ioutil"
)

func newProvidedCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
cmd := &cobra.Command{
Use: "provided",
Short: `Manage "provided" certificate authorities`,
Long: `Manage "provided" certificate authorities.`,
}
// sub-commands
cmd.AddCommand(newCertificatesCmd(pctx))
return cmd
}

func newCertificatesCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
cmd := &cobra.Command{
Use: "certificates",
Short: `Manage signing certificates used by a "provided" certificate authority`,
Long: `Manage signing certificates used by a "provided" certificate authority.`,
}
// sub-commands
cmd.AddCommand(newAddCertificateCmd(pctx))
cmd.AddCommand(newListCertificatesCmd(pctx))
cmd.AddCommand(newDeleteCertificateCmd(pctx))
return cmd
}

type addCertificateContext struct {
*kumactl_cmd.RootContext

args struct {
keyFile string
certFile string
}
}

func newAddCertificateCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
ctx := addCertificateContext{RootContext: pctx}
cmd := &cobra.Command{
Use: "add",
Short: "Add signing certificate",
Long: `Add signing certificate.`,
RunE: func(cmd *cobra.Command, _ []string) error {
client, err := ctx.CurrentProvidedCaClient()
if err != nil {
return err
}
certBytes, err := ioutil.ReadFile(ctx.args.certFile)
if err != nil {
return errors.Wrap(err, "could not read content of the certificate file")
}
keyBytes, err := ioutil.ReadFile(ctx.args.keyFile)
if err != nil {
return errors.Wrap(err, "could not read content of the key file")
}
pair := tls.KeyPair{
CertPEM: certBytes,
KeyPEM: keyBytes,
}
signingCert, err := client.AddSigningCertificate(ctx.CurrentMesh(), pair)
if err != nil {
return err
}
cmd.Printf("added certificate %q", signingCert.Id)
return nil
},
}
cmd.Flags().StringVar(&ctx.args.keyFile, "key-file", "", "path to a file with a private key")
_ = cmd.MarkFlagRequired("key-file")
cmd.Flags().StringVar(&ctx.args.certFile, "cert-file", "", "path to a file with a CA certificate")
_ = cmd.MarkFlagRequired("cert-file")
return cmd
}

func newListCertificatesCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List signing certificates",
Long: `List signing certificates.`,
RunE: func(cmd *cobra.Command, _ []string) error {
client, err := pctx.CurrentProvidedCaClient()
if err != nil {
return err
}
certs, err := client.SigningCertificates(pctx.CurrentMesh())
if err != nil {
return errors.Wrap(err, "could not retrieve signing certificates")
}
if err := printListCertificates(certs, cmd.OutOrStdout()); err != nil {
return errors.Wrap(err, "could not print certificates")
}
return nil
},
}
return cmd
}

func printListCertificates(certs []types.SigningCert, out io.Writer) error {
x509Certs := make([]*x509.Certificate, len(certs))
for i, cert := range certs {
block, _ := pem.Decode([]byte(cert.Cert))
x509Cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return errors.Wrap(err, "could not parse certificate")
}
x509Certs[i] = x509Cert
}
data := printers.Table{
Headers: []string{"ID", "COMMON NAME", "SERIAL NUMBER", "NOT VALID BEFORE", "NOT VALID AFTER", "SHA-1 FINGERPRINT"},
NextRow: func() func() []string {
i := 0
return func() []string {
defer func() { i++ }()
if len(certs) <= i {
return nil
}
cert := certs[i]
x509Cert := x509Certs[i]
return []string{
cert.Id, // ID
x509Cert.Subject.CommonName, // COMMON NAME
x509Cert.SerialNumber.String(), // SERIAL NUMBER
x509Cert.NotBefore.String(), // NOT VALID BEFORE
x509Cert.NotAfter.String(), // NOT VALID AFTER
fmt.Sprintf("%x", sha1.Sum(x509Cert.Raw)), // SHA-1 FINGERPRINT
}
}
}(),
}
return printers.NewTablePrinter().Print(data, out)
}

type deleteCertificateContext struct {
*kumactl_cmd.RootContext
args struct {
id string
}
}

func newDeleteCertificateCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
ctx := deleteCertificateContext{RootContext: pctx}
cmd := &cobra.Command{
Use: "delete",
Short: "Delete signing certificate",
Long: `Delete signing certificate.`,
RunE: func(cmd *cobra.Command, _ []string) error {
client, err := pctx.CurrentProvidedCaClient()
if err != nil {
return err
}
if err := client.DeleteSigningCertificate(pctx.CurrentMesh(), ctx.args.id); err != nil {
return errors.Wrap(err, "could not delete signing certificate")
}
cmd.Printf("removed certificate %q", ctx.args.id)
return nil
},
}
cmd.Flags().StringVar(&ctx.args.id, "id", "", "id of the certificate")
_ = cmd.MarkFlagRequired("id")
return cmd
}
Loading

0 comments on commit bc7f348

Please sign in to comment.