Repository: nats-io/nsc (go)

Issue:
init command doesn't give an error when on-boarding ngs
```
nsc init -o synadia -n ZimplerTest
[ OK ] add managed operator synadia
[ERR ] push jwt to account server:
       [ERR ] failed to push account to remote server
       > bad JWT in request
[WARN] perform push/pull again or exchange self-signed JWT manually
[ OK ] created account ZimplerTest
[ OK ] created user "ZimplerTest"
[ OK ] project jwt files created in `~/.nsc/nats`
[ OK ] user creds file stored in `~/.nkeys/creds/synadia/ZimplerTest/ZimplerTest.creds`
Error: init failed: 1 job failed - 5 jobs succeeded and 0 had warnings

```

Pull request:
init command didn't perform a check on the jwt version
[fix] the init command didn't test the operator JWT version
FIX #382

Patch:
diff --git a/cmd/addoperator.go b/cmd/addoperator.go
index ba80b01..30a776a 100644
--- a/cmd/addoperator.go
+++ b/cmd/addoperator.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2019 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -57,8 +57,12 @@ func init() {
 }
 
 func JWTUpgradeBannerJWT(ver int) error {
-	return fmt.Errorf(`this version of nsc (%s) is incompatible with the provided jwt v%d`,
-		GetRootCmd().Version, ver)
+	extra := ""
+	if ver == 1 {
+		extra = " - please downgrade to 0.5.0 by executing `nsc update --version 0.5.0`."
+	}
+	return fmt.Errorf(`the operator jwt (v%d) is incompatible this version of nsc%s`,
+		ver, extra)
 }
 
 type AddOperatorParams struct {
diff --git a/cmd/init.go b/cmd/init.go
index 3338eea..61c29da 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2019 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -266,6 +266,9 @@ func (p *InitCmdParams) createStore(cmd *cobra.Command) error {
 		if err != nil {
 			return fmt.Errorf("error decoding operator jwt: %v", err)
 		}
+		if op.Version != 2 {
+			return JWTUpgradeBannerJWT(op.Version)
+		}
 		onk.Name = GetOperatorName(op.Name, p.OperatorJwtURL)
 		p.AccountServerURL = op.AccountServerURL
 
diff --git a/go.mod b/go.mod
index 1797656..8530387 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,6 @@ require (
 	github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0
 	github.com/nats-io/nkeys v0.3.0
 	github.com/nats-io/nuid v1.0.1
-	github.com/onsi/ginkgo v1.7.0 // indirect
 	github.com/onsi/gomega v1.4.3 // indirect
 	github.com/rhysd/go-github-selfupdate v1.2.2
 	github.com/spf13/cast v1.3.0 // indirect
diff --git a/go.sum b/go.sum
index 8abd180..33e0ec0 100644
--- a/go.sum
+++ b/go.sum
@@ -40,7 +40,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
 github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
-github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
 github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
@@ -76,7 +75,6 @@ github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
 github.com/nats-io/cliprompts/v2 v2.0.0-20191226174129-372d79b36768 h1:sdr8zfPeN/b4/TDoxbD9ARAtyP92zDFDvj87MeAAyjk=
 github.com/nats-io/cliprompts/v2 v2.0.0-20191226174129-372d79b36768/go.mod h1:oweZn7AeaVJYKlNHfCIhznJVsdySLSng55vfuINE/d0=
 github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7 h1:RnGotxlghqR5D2KDAu4TyuLqyjuylOsJiAFhXvMvQIc=
 github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M=
 github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M=
 github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU=
@@ -97,15 +95,12 @@ github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0 h1:s//xxvMgNRVJ
 github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0/go.mod h1:VU2zERjp8xmF+Lw2NH4u2t5qWZxwc7jB3+7HVMWQXPI=
 github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
-github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM=
 github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
 github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
 github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
 github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
-github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -146,7 +141,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
 golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
@@ -169,11 +163,9 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
@@ -196,9 +188,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=


Test patch:
diff --git a/cmd/addoperator_test.go b/cmd/addoperator_test.go
index d6efe8f..14589a7 100644
--- a/cmd/addoperator_test.go
+++ b/cmd/addoperator_test.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2019 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -227,7 +227,7 @@ func Test_AddWellKnownOperator(t *testing.T) {
 
 	// create the managed operator store
 	_, opk, okp := CreateOperatorKey(t)
-	as, _ := RunTestAccountServerWithOperatorKP(t, okp)
+	as, _ := RunTestAccountServerWithOperatorKP(t, okp, 2)
 	defer as.Close()
 
 	// add an entry to well known
diff --git a/cmd/generateactivation_test.go b/cmd/generateactivation_test.go
index 0233b1b..21b385f 100644
--- a/cmd/generateactivation_test.go
+++ b/cmd/generateactivation_test.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2019 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -229,7 +229,7 @@ func Test_GenerateActivationUsingSigningKey(t *testing.T) {
 
 func Test_InteractiveGenerateActivationPush(t *testing.T) {
 	_, _, okp := CreateOperatorKey(t)
-	as, m := RunTestAccountServerWithOperatorKP(t, okp)
+	as, m := RunTestAccountServerWithOperatorKP(t, okp, 2)
 	defer as.Close()
 
 	ts := NewTestStoreWithOperator(t, "T", okp)
diff --git a/cmd/init_test.go b/cmd/init_test.go
index f9d62ae..01e8db9 100644
--- a/cmd/init_test.go
+++ b/cmd/init_test.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2019 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -176,6 +176,37 @@ func Test_InitWellKnown2(t *testing.T) {
 	ts.VerifyUser(t, "T", "B", "B", true)
 }
 
+func Test_InitWellKnownV1Operator(t *testing.T) {
+	ts := NewTestStore(t, "X")
+	defer ts.Done(t)
+
+	_, _, okp := CreateOperatorKey(t)
+	// run a jwt account server
+	as, _ := RunTestAccountServerWithOperatorKP(t, okp, 1)
+	defer as.Close()
+
+	// add an entry to well known
+	ourl, err := url.Parse(as.URL)
+	require.NoError(t, err)
+	ourl.Path = "/jwt/v1/operator"
+
+	var twko KnownOperator
+	twko.AccountServerURL = ourl.String()
+	twko.Name = "T"
+
+	// make it be the first
+	var wkops KnownOperators
+	wkops = append(wkops, twko)
+
+	ops, _ := GetWellKnownOperators()
+	wkops = append(wkops, ops...)
+	wellKnownOperators = wkops
+
+	_, _, err = ExecuteCmd(createInitCmd(), "--remote-operator", "T", "--name", "A")
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "the operator jwt (v1) is incompatible this version of nsc")
+}
+
 func Test_InitWellKnownInteractive(t *testing.T) {
 	as, m := RunTestAccountServer(t)
 	defer as.Close()
diff --git a/cmd/migrate_test.go b/cmd/migrate_test.go
index 32f9668..cd07752 100644
--- a/cmd/migrate_test.go
+++ b/cmd/migrate_test.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2019 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -94,7 +94,7 @@ func Test_MigrateSingleInteractive(t *testing.T) {
 
 func Test_MigrateManaged(t *testing.T) {
 	_, opk, okp := CreateOperatorKey(t)
-	as, m := RunTestAccountServerWithOperatorKP(t, okp)
+	as, m := RunTestAccountServerWithOperatorKP(t, okp, 2)
 	defer as.Close()
 
 	// create the managed operator store
diff --git a/cmd/push_test.go b/cmd/push_test.go
index 2b05ac7..36bc594 100644
--- a/cmd/push_test.go
+++ b/cmd/push_test.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -31,7 +31,7 @@ import (
 
 func Test_SyncOK(t *testing.T) {
 	_, _, okp := CreateOperatorKey(t)
-	as, m := RunTestAccountServerWithOperatorKP(t, okp)
+	as, m := RunTestAccountServerWithOperatorKP(t, okp, 2)
 	defer as.Close()
 
 	ts := NewTestStoreWithOperator(t, "T", okp)
@@ -55,7 +55,7 @@ func Test_SyncOK(t *testing.T) {
 
 func Test_SyncNoURL(t *testing.T) {
 	_, _, okp := CreateOperatorKey(t)
-	as, m := RunTestAccountServerWithOperatorKP(t, okp)
+	as, m := RunTestAccountServerWithOperatorKP(t, okp, 2)
 	ts := NewTestStoreWithOperatorJWT(t, string(m["operator"]))
 	ts.AddAccount(t, "A")
 	as.Close()
@@ -103,7 +103,7 @@ func Test_SyncManaged(t *testing.T) {
 
 func Test_SyncManualServer(t *testing.T) {
 	_, _, okp := CreateOperatorKey(t)
-	as, m := RunTestAccountServerWithOperatorKP(t, okp)
+	as, m := RunTestAccountServerWithOperatorKP(t, okp, 2)
 	defer as.Close()
 
 	// remove the account server
diff --git a/cmd/util_test.go b/cmd/util_test.go
index a30b81d..8e65457 100644
--- a/cmd/util_test.go
+++ b/cmd/util_test.go
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 The NATS Authors
+ * Copyright 2018-2021 The NATS Authors
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -30,6 +30,7 @@ import (
 	"time"
 
 	cli "github.com/nats-io/cliprompts/v2"
+	jwt1 "github.com/nats-io/jwt"
 	"github.com/nats-io/jwt/v2"
 	"github.com/nats-io/nats-server/v2/server"
 	nats "github.com/nats-io/nats.go"
@@ -665,7 +666,7 @@ func Test_Util(t *testing.T) {
 	require.Equal(t, pk, ac2.Issuer)
 }
 
-func RunTestAccountServerWithOperatorKP(t *testing.T, okp nkeys.KeyPair) (*httptest.Server, map[string][]byte) {
+func RunTestAccountServerWithOperatorKP(t *testing.T, okp nkeys.KeyPair, vers int) (*httptest.Server, map[string][]byte) {
 	storage := make(map[string][]byte)
 	opk, err := okp.PublicKey()
 	require.NoError(t, err)
@@ -770,16 +771,29 @@ func RunTestAccountServerWithOperatorKP(t *testing.T, okp nkeys.KeyPair) (*httpt
 		}
 	}))
 
-	oc := jwt.NewOperatorClaims(opk)
-	oc.Name = "T"
-	oc.Subject = opk
-	u, err := url.Parse(tas.URL)
-	require.NoError(t, err)
-	u.Path = "jwt/v1"
-	oc.AccountServerURL = u.String()
-	token, err := oc.Encode(okp)
-	require.NoError(t, err)
-	storage["operator"] = []byte(token)
+	if vers == 1 {
+		oc := jwt1.NewOperatorClaims(opk)
+		oc.Name = "T"
+		oc.Subject = opk
+		u, err := url.Parse(tas.URL)
+		require.NoError(t, err)
+		u.Path = "jwt/v1"
+		oc.AccountServerURL = u.String()
+		token, err := oc.Encode(okp)
+		require.NoError(t, err)
+		storage["operator"] = []byte(token)
+	} else {
+		oc := jwt.NewOperatorClaims(opk)
+		oc.Name = "T"
+		oc.Subject = opk
+		u, err := url.Parse(tas.URL)
+		require.NoError(t, err)
+		u.Path = "jwt/v1"
+		oc.AccountServerURL = u.String()
+		token, err := oc.Encode(okp)
+		require.NoError(t, err)
+		storage["operator"] = []byte(token)
+	}
 
 	return tas, storage
 }
@@ -787,5 +801,5 @@ func RunTestAccountServerWithOperatorKP(t *testing.T, okp nkeys.KeyPair) (*httpt
 // Runs a TestAccountServer returning the server and the underlying storage
 func RunTestAccountServer(t *testing.T) (*httptest.Server, map[string][]byte) {
 	_, _, okp := CreateOperatorKey(t)
-	return RunTestAccountServerWithOperatorKP(t, okp)
+	return RunTestAccountServerWithOperatorKP(t, okp, 2)
 }