diff --git a/cmd/aserto/main.go b/cmd/aserto/main.go index da139ac..d4c53b5 100644 --- a/cmd/aserto/main.go +++ b/cmd/aserto/main.go @@ -66,6 +66,11 @@ func main() { func run(ctx context.Context) (exitCode int) { fflag.Init() + cwd, err := os.Getwd() + if err != nil { + return exitErr(errors.Wrap(err, "failed to determine current working directory")) + } + home, err := os.UserHomeDir() if err != nil { return exitErr(errors.Wrap(err, "failed to determine user home directory")) @@ -120,6 +125,7 @@ func run(ctx context.Context) (exitCode int) { "insecure": strconv.FormatBool(topazCC.Insecure()), "no_check": strconv.FormatBool(topazCC.NoCheck()), "no_color": strconv.FormatBool(topazCC.NoColor()), + "cwd": cwd, }, ) diff --git a/pkg/handlers/control_plane/client_cert.go b/pkg/handlers/control_plane/client_cert.go index ee68ec4..1ab0208 100644 --- a/pkg/handlers/control_plane/client_cert.go +++ b/pkg/handlers/control_plane/client_cert.go @@ -1,6 +1,12 @@ package controlplane import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "time" + "github.com/aserto-dev/aserto/pkg/cc" "github.com/aserto-dev/go-grpc/aserto/api/v1" "github.com/aserto-dev/go-grpc/aserto/tenant/connection/v1" @@ -10,10 +16,16 @@ import ( ) type ClientCertCmd struct { - ID string `arg:"" help:"edge authorizer connection ID"` + ID string `arg:"" help:"edge authorizer connection ID"` + Directory string `flag:"" short:"d" help:"directory to save certificate file" default:"${cwd}"` + Raw bool `flag:"" help:"raw message output"` } func (cmd ClientCertCmd) Run(c *cc.CommonCtx) error { + if cmd.ID == "" { + return errors.New("connection ID argument not provided") + } + cli, err := c.TenantClient(c.Context) if err != nil { return err @@ -35,15 +47,78 @@ func (cmd ClientCertCmd) Run(c *cc.CommonCtx) error { return errors.New("not an edge authorizer connection") } - certs := conn.Config.Fields["api_cert"].GetListValue().GetValues() - if len(certs) == 0 { + var cfg Config + if buf, err := conn.Config.MarshalJSON(); err == nil { + if err := json.Unmarshal(buf, &cfg); err != nil { + return err + } + } else { + return err + } + + if len(cfg.APICerts) == 0 { return errors.New("invalid connection configuration") } - err = jsonx.OutputJSONPB(c.StdOut(), certs[len(certs)-1]) - if err != nil { + cert := cfg.APICerts[len(cfg.APICerts)-1] + + if cmd.Raw { + return jsonx.OutputJSON(c.StdOut(), cert) + } + + c.Con().Info().Msg("ID : %s", cert.ID) + c.Con().Info().Msg("CN : %s", cert.CN) + c.Con().Info().Msg("Exp: %s", cert.Expiration) + + if err := cmd.writeFile(c, sidecarKey, cert.Key); err != nil { + return err + } + + if err := cmd.writeFile(c, sidecarCert, cert.Cert); err != nil { return err } return nil } + +const ( + sidecarKey string = "sidecar.key" + sidecarCert string = "sidecar.crt" +) + +type Config struct { + APICerts []APICert `json:"api_cert"` +} + +type APICert struct { + ID string `json:"id"` + CN string `json:"common_name"` + Key string `json:"private_key"` + Cert string `json:"certificate"` + Expiration time.Time `json:"expiration"` +} + +func (cmd ClientCertCmd) writeFile(c *cc.CommonCtx, name, value string) error { + if fi, err := os.Stat(cmd.Directory); err != nil || !fi.IsDir() { + if err != nil { + return err + } + if !fi.IsDir() { + return errors.Errorf("--directory argument %q is not a directory", cmd.Directory) + } + } + + fn := filepath.Join(cmd.Directory, name) + + c.Con().Msg(fn) + + w, err := os.Create(fn) + if err != nil { + return err + } + defer w.Close() + + _, err = fmt.Fprintln(w, value) + + return err +}