github.com/nats-io/nsc/v2@v2.8.7-0.20240307184528-efd7023c6896/cmd/describeuser_test.go (about) 1 /* 2 * Copyright 2018-2023 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package cmd 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "os" 22 "path/filepath" 23 "strings" 24 "testing" 25 26 "github.com/nats-io/jwt/v2" 27 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestDescribeUser_Single(t *testing.T) { 32 ts := NewTestStore(t, "operator") 33 defer ts.Done(t) 34 35 ts.AddAccount(t, "A") 36 ts.AddUser(t, "A", "a") 37 38 pub := ts.GetUserPublicKey(t, "A", "a") 39 apub := ts.GetAccountPublicKey(t, "A") 40 41 stdout, _, err := ExecuteCmd(createDescribeUserCmd()) 42 require.NoError(t, err) 43 // account A public key 44 require.Contains(t, stdout, apub) 45 // operator public key 46 require.Contains(t, stdout, pub) 47 // name for the account 48 require.Contains(t, stdout, " a ") 49 } 50 51 func TestDescribeUserRaw(t *testing.T) { 52 ts := NewTestStore(t, "operator") 53 defer ts.Done(t) 54 55 ts.AddAccount(t, "A") 56 ts.AddUser(t, "A", "U") 57 58 Raw = true 59 stdout, _, err := ExecuteCmd(createDescribeUserCmd()) 60 require.NoError(t, err) 61 62 uc, err := jwt.DecodeUserClaims(stdout) 63 require.NoError(t, err) 64 65 require.NotNil(t, uc) 66 require.Equal(t, "U", uc.Name) 67 } 68 69 func TestDescribeUser_Multiple(t *testing.T) { 70 ts := NewTestStore(t, "operator") 71 defer ts.Done(t) 72 73 ts.AddAccount(t, "A") 74 ts.AddUser(t, "A", "a") 75 ts.AddUser(t, "A", "b") 76 77 _, stderr, err := ExecuteCmd(createDescribeUserCmd()) 78 require.Error(t, err) 79 require.Contains(t, stderr, "user is required") 80 } 81 82 func TestDescribeUser_MultipleWithContext(t *testing.T) { 83 ts := NewTestStore(t, "operator") 84 defer ts.Done(t) 85 86 ts.AddAccount(t, "A") 87 ts.AddUser(t, "A", "a") 88 ts.AddAccount(t, "B") 89 ts.AddUser(t, "B", "b") 90 91 err := GetConfig().SetAccount("B") 92 require.NoError(t, err) 93 94 apub := ts.GetAccountPublicKey(t, "B") 95 96 pub := ts.GetUserPublicKey(t, "B", "b") 97 98 stdout, _, err := ExecuteCmd(createDescribeUserCmd()) 99 require.NoError(t, err) 100 require.Contains(t, stdout, apub) 101 require.Contains(t, stdout, pub) 102 require.Contains(t, stdout, " b ") 103 } 104 105 func TestDescribeUser_MultipleWithFlag(t *testing.T) { 106 ts := NewTestStore(t, "operator") 107 defer ts.Done(t) 108 109 ts.AddAccount(t, "A") 110 ts.AddAccount(t, "B") 111 ts.AddUser(t, "B", "b") 112 ts.AddUser(t, "B", "bb") 113 114 _, stderr, err := ExecuteCmd(createDescribeUserCmd(), "--account", "B") 115 require.Error(t, err) 116 require.Contains(t, stderr, "user is required") 117 118 apub := ts.GetAccountPublicKey(t, "B") 119 120 pub := ts.GetUserPublicKey(t, "B", "bb") 121 122 stdout, _, err := ExecuteCmd(createDescribeUserCmd(), "--account", "B", "--name", "bb") 123 require.NoError(t, err) 124 require.Contains(t, stdout, apub) 125 require.Contains(t, stdout, pub) 126 require.Contains(t, stdout, " bb ") 127 } 128 129 func TestDescribeUser_MultipleWithBadUser(t *testing.T) { 130 ts := NewTestStore(t, "operator") 131 defer ts.Done(t) 132 133 ts.AddAccount(t, "A") 134 ts.AddAccount(t, "B") 135 ts.AddUser(t, "B", "b") 136 137 _, _, err := ExecuteCmd(createDescribeUserCmd(), "--account", "A") 138 require.Error(t, err) 139 140 _, _, err = ExecuteCmd(createDescribeUserCmd(), "--account", "B", "--name", "a") 141 require.Error(t, err) 142 143 _, _, err = ExecuteCmd(createDescribeUserCmd(), "--account", "B", "--name", "b") 144 require.NoError(t, err) 145 } 146 147 func TestDescribeUser_Interactive(t *testing.T) { 148 ts := NewTestStore(t, "operator") 149 defer ts.Done(t) 150 151 ts.AddAccount(t, "A") 152 ts.AddAccount(t, "B") 153 ts.AddUser(t, "B", "bb") 154 155 _, _, err := ExecuteInteractiveCmd(createDescribeUserCmd(), []interface{}{1, 0}) 156 require.NoError(t, err) 157 } 158 159 func TestDescribeUser_Account(t *testing.T) { 160 ts := NewTestStore(t, "operator") 161 defer ts.Done(t) 162 163 ts.AddAccount(t, "A") 164 _, pub, kp := CreateAccountKey(t) 165 _, _, err := ExecuteCmd(createEditAccount(), "--name", "A", "--sk", pub) 166 require.NoError(t, err) 167 168 // signed with default account key 169 ts.AddUser(t, "A", "aa") 170 stdout, _, err := ExecuteCmd(createDescribeUserCmd(), "--account", "A", "--name", "aa") 171 require.NoError(t, err) 172 require.NotContains(t, stdout, "Issuer Account") 173 174 // signed with a signing key 175 ts.AddUserWithSigner(t, "A", "bb", kp) 176 require.NoError(t, err) 177 stdout, _, err = ExecuteCmd(createDescribeUserCmd(), "--account", "A", "--name", "bb") 178 require.NoError(t, err) 179 require.Contains(t, stdout, "Issuer Account") 180 } 181 182 func TestDescribeRawUser(t *testing.T) { 183 ts := NewTestStore(t, "operator") 184 defer ts.Done(t) 185 186 ts.AddAccount(t, "A") 187 _, pub, kp := CreateAccountKey(t) 188 _, _, err := ExecuteCmd(createEditAccount(), "--name", "A", "--sk", pub) 189 require.NoError(t, err) 190 191 // signed with default account key 192 ts.AddUser(t, "A", "aa") 193 stdout, _, err := ExecuteCmd(createDescribeUserCmd(), "--account", "A", "--name", "aa") 194 require.NoError(t, err) 195 require.NotContains(t, stdout, "Issuer Account") 196 197 // signed with a signing key 198 ts.AddUserWithSigner(t, "A", "bb", kp) 199 require.NoError(t, err) 200 stdout, _, err = ExecuteCmd(createDescribeUserCmd(), "--account", "A", "--name", "bb") 201 require.NoError(t, err) 202 require.Contains(t, stdout, "Issuer Account") 203 } 204 205 func TestDescribeUser_Json(t *testing.T) { 206 ts := NewTestStore(t, "O") 207 defer ts.Done(t) 208 209 ts.AddAccount(t, "A") 210 ts.AddUser(t, "A", "aa") 211 212 out, _, err := ExecuteCmd(rootCmd, "describe", "user", "--json") 213 require.NoError(t, err) 214 m := make(map[string]interface{}) 215 err = json.Unmarshal([]byte(out), &m) 216 require.NoError(t, err) 217 uc, err := ts.Store.ReadUserClaim("A", "aa") 218 require.NoError(t, err) 219 require.NotNil(t, uc) 220 require.Equal(t, uc.Subject, m["sub"]) 221 } 222 223 func TestDescribeUser_JsonPath(t *testing.T) { 224 ts := NewTestStore(t, "O") 225 defer ts.Done(t) 226 227 ts.AddAccount(t, "A") 228 ts.AddUser(t, "A", "aa") 229 230 out, _, err := ExecuteCmd(rootCmd, "describe", "user", "--field", "sub") 231 require.NoError(t, err) 232 uc, err := ts.Store.ReadUserClaim("A", "aa") 233 require.NoError(t, err) 234 require.Equal(t, fmt.Sprintf("\"%s\"\n", uc.Subject), out) 235 } 236 237 func TestDescribeUser_Times(t *testing.T) { 238 ts := NewTestStore(t, "operator") 239 defer ts.Done(t) 240 241 ts.AddAccount(t, "A") 242 ts.AddUser(t, "A", "aa") 243 _, _, err := ExecuteCmd(createEditUserCmd(), "--time", "16:04:05-17:04:09") 244 require.NoError(t, err) 245 246 stdout, _, err := ExecuteCmd(createDescribeUserCmd(), "--account", "A", "--name", "aa") 247 require.NoError(t, err) 248 require.Contains(t, stdout, "16:04:05-17:04:09") 249 } 250 251 func TestDescribeUser_Output(t *testing.T) { 252 ts := NewTestStore(t, "O") 253 defer ts.Done(t) 254 255 ts.AddAccount(t, "A") 256 ts.AddUser(t, "A", "aa") 257 258 p := filepath.Join(ts.Dir, "aa.json") 259 _, _, err := ExecuteCmd(rootCmd, "describe", "user", "-a", "A", "--json", "--output-file", p) 260 require.NoError(t, err) 261 data, err := os.ReadFile(p) 262 require.NoError(t, err) 263 uc := jwt.UserClaims{} 264 require.NoError(t, json.Unmarshal(data, &uc)) 265 require.Equal(t, "aa", uc.Name) 266 267 p = filepath.Join(ts.Dir, "aa.txt") 268 _, _, err = ExecuteCmd(rootCmd, "describe", "user", "-a", "A", "--output-file", p) 269 require.NoError(t, err) 270 data, err = os.ReadFile(p) 271 require.NoError(t, err) 272 strings.Contains(string(data), "User Details") 273 274 p = filepath.Join(ts.Dir, "aa.jwt") 275 _, _, err = ExecuteCmd(rootCmd, "describe", "user", "-a", "A", "--raw", "--output-file", p) 276 require.NoError(t, err) 277 data, err = os.ReadFile(p) 278 require.NoError(t, err) 279 require.Contains(t, string(data), "-----BEGIN NATS USER JWT-----\ney") 280 }