github.com/nats-io/nsc@v0.0.0-20221206222106-35db9400b257/cmd/tools_test.go (about) 1 /* 2 * Copyright 2018-2019 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 "fmt" 20 "log" 21 "path/filepath" 22 "strings" 23 "testing" 24 "time" 25 26 nats "github.com/nats-io/nats.go" 27 "github.com/nats-io/nuid" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestPub(t *testing.T) { 32 ts := NewTestStore(t, "O") 33 defer ts.Done(t) 34 ts.AddAccount(t, "A") 35 ts.AddUser(t, "A", "U") 36 37 // create the basic configuration 38 serverconf := filepath.Join(ts.Dir, "server.conf") 39 _, _, err := ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 40 "--config-file", serverconf) 41 require.NoError(t, err) 42 43 // start a server with the config at a random port 44 ports := ts.RunServerWithConfig(t, serverconf) 45 46 // with the captured ports, regenerate the operator jwt 47 // we only need the client to update 48 _, _, err = ExecuteCmd(createEditOperatorCmd(), 49 "--service-url", strings.Join(ports.Nats, ",")) 50 require.NoError(t, err) 51 52 // create a conn to the server 53 nc, err := nats.Connect(strings.Join(ports.Nats, ","), 54 nats.UserCredentials(ts.KeyStore.CalcUserCredsPath("A", "U"))) 55 require.NoError(t, err) 56 defer nc.Close() 57 58 // generate a random subject/payload 59 v := nuid.Next() 60 c := make(chan *nats.Msg) 61 _, err = nc.Subscribe(v, func(m *nats.Msg) { 62 c <- m 63 }) 64 require.NoError(t, err) 65 require.NoError(t, nc.Flush()) 66 67 // pub a message 68 _, _, err = ExecuteCmd(createPubCmd(), v, v) 69 require.NoError(t, err) 70 71 control := <-c 72 require.NotNil(t, control) 73 require.Equal(t, control.Subject, v) 74 require.Equal(t, []byte(v), control.Data) 75 } 76 77 func TestPubPermissionViolation(t *testing.T) { 78 ts := NewTestStore(t, "O") 79 defer ts.Done(t) 80 ts.AddAccount(t, "A") 81 82 // generate a random subject/payload 83 v := nuid.Next() 84 85 ts.AddUser(t, "A", "U") 86 _, _, err := ExecuteCmd(createEditUserCmd(), "--deny-pub", v) 87 require.NoError(t, err) 88 89 // create the basic configuration 90 serverconf := filepath.Join(ts.Dir, "server.conf") 91 _, _, err = ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 92 "--config-file", serverconf) 93 require.NoError(t, err) 94 95 // start a server with the config at a random port 96 ports := ts.RunServerWithConfig(t, serverconf) 97 98 // with the captured ports, regenerate the operator jwt 99 // we only need the client to update 100 _, _, err = ExecuteCmd(createEditOperatorCmd(), 101 "--service-url", strings.Join(ports.Nats, ",")) 102 require.NoError(t, err) 103 104 // create a conn to the server 105 nc, err := nats.Connect(strings.Join(ports.Nats, ","), 106 nats.UserCredentials(ts.KeyStore.CalcUserCredsPath("A", "U"))) 107 require.NoError(t, err) 108 defer nc.Close() 109 110 // pub a message 111 _, _, err = ExecuteCmd(createPubCmd(), v, v) 112 require.Error(t, err) 113 require.Contains(t, err.Error(), "Permissions Violation") 114 } 115 116 func TestSub(t *testing.T) { 117 ts := NewTestStore(t, "O") 118 defer ts.Done(t) 119 ts.AddAccount(t, "A") 120 ts.AddUser(t, "A", "U") 121 122 // create the basic configuration 123 conf := filepath.Join(ts.Dir, "server.conf") 124 _, _, err := ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 125 "--config-file", conf) 126 require.NoError(t, err) 127 128 // start a server with the config at a random port 129 ports := ts.RunServerWithConfig(t, conf) 130 131 // with the captured ports, regenerate the operator jwt - we only need the client to update 132 _, _, err = ExecuteCmd(createEditOperatorCmd(), 133 "--service-url", strings.Join(ports.Nats, ",")) 134 require.NoError(t, err) 135 136 // generate a random subject/payload 137 v := nuid.Next() 138 139 log.SetFlags(log.LstdFlags) 140 // subscribe a message 141 type po struct { 142 stdout string 143 stderr string 144 err error 145 } 146 c := make(chan po) 147 go func() { 148 var r po 149 r.stdout, r.stderr, r.err = ExecuteCmd(createSubCmd(), "--max-messages", "1", v) 150 c <- r 151 }() 152 153 // wait for client 154 ts.WaitForClient(t, "nsc_sub", 1, 60*time.Second) 155 156 // create a conn to the server 157 creds := ts.KeyStore.CalcUserCredsPath("A", "U") 158 nc := ts.CreateClient(t, nats.UserCredentials(creds)) 159 require.NoError(t, nc.Flush()) 160 err = nc.Publish(v, []byte(v)) 161 require.NoError(t, err) 162 require.NoError(t, nc.Flush()) 163 164 select { 165 case r := <-c: 166 t.Log(r.stdout) 167 t.Log(r.stderr) 168 t.Log(r.err) 169 require.NoError(t, r.err) 170 require.Contains(t, r.stderr, fmt.Sprintf("received on [%s]: '%s'", v, v)) 171 case <-time.After(25 * time.Second): 172 t.Fatal("timed out") 173 } 174 } 175 176 func TestSubPermissionViolation(t *testing.T) { 177 ts := NewTestStore(t, "O") 178 defer ts.Done(t) 179 ts.AddAccount(t, "A") 180 181 // generate a random subject/payload 182 v := nuid.Next() 183 184 ts.AddUser(t, "A", "U") 185 _, _, err := ExecuteCmd(createEditUserCmd(), "--deny-sub", v) 186 require.NoError(t, err) 187 188 // create the basic configuration 189 conf := filepath.Join(ts.Dir, "server.conf") 190 _, _, err = ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 191 "--config-file", conf) 192 require.NoError(t, err) 193 194 // start a server with the config at a random port 195 ports := ts.RunServerWithConfig(t, conf) 196 197 // with the captured ports, regenerate the operator jwt - we only need the client to update 198 _, _, err = ExecuteCmd(createEditOperatorCmd(), 199 "--service-url", strings.Join(ports.Nats, ",")) 200 require.NoError(t, err) 201 202 log.SetFlags(log.LstdFlags) 203 204 _, _, err = ExecuteCmd(createSubCmd(), "--max-messages", "1", v) 205 require.Error(t, err) 206 require.Contains(t, err.Error(), "Permissions Violation") 207 } 208 209 func TestReq(t *testing.T) { 210 ts := NewTestStore(t, "O") 211 defer ts.Done(t) 212 ts.AddAccount(t, "A") 213 ts.AddUser(t, "A", "U") 214 215 // create the basic configuration 216 conf := filepath.Join(ts.Dir, "server.conf") 217 218 _, _, err := ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 219 "--config-file", conf) 220 require.NoError(t, err) 221 222 // start a server with the config at a random port 223 ports := ts.RunServerWithConfig(t, conf) 224 225 // with the captured ports, regenerate the operator jwt - we only need the client to update 226 _, _, err = ExecuteCmd(createEditOperatorCmd(), 227 "--service-url", strings.Join(ports.Nats, ",")) 228 require.NoError(t, err) 229 230 // generate a random subject/payload 231 v := nuid.Next() 232 233 // create a conn to the server 234 creds := ts.KeyStore.CalcUserCredsPath("A", "U") 235 nc := ts.CreateClient(t, nats.UserCredentials(creds)) 236 require.NoError(t, nc.Flush()) 237 sub, err := nc.Subscribe(v, func(m *nats.Msg) { 238 require.NotEmpty(t, m.Reply) 239 // reply with the payload in uppercase 240 require.NoError(t, m.Respond([]byte(strings.ToUpper(string(m.Data))))) 241 }) 242 require.NoError(t, err) 243 require.NoError(t, sub.AutoUnsubscribe(1)) 244 require.NoError(t, nc.Flush()) 245 246 _, stderr, err := ExecuteCmd(createToolReqCmd(), v, v) 247 require.NoError(t, err) 248 require.Contains(t, stderr, strings.ToUpper(v)) 249 } 250 251 func TestReply(t *testing.T) { 252 ts := NewTestStore(t, "O") 253 defer ts.Done(t) 254 ts.AddAccount(t, "A") 255 ts.AddUser(t, "A", "U") 256 257 // create the basic configuration 258 conf := filepath.Join(ts.Dir, "server.conf") 259 _, _, err := ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 260 "--config-file", conf) 261 require.NoError(t, err) 262 263 // start a server with the config at a random port 264 ports := ts.RunServerWithConfig(t, conf) 265 266 // with the captured ports, regenerate the operator jwt - we only need the client to update 267 _, _, err = ExecuteCmd(createEditOperatorCmd(), 268 "--service-url", strings.Join(ports.Nats, ",")) 269 require.NoError(t, err) 270 271 // generate a random subject/payload 272 v := nuid.Next() 273 274 // subscribe a message 275 type po struct { 276 stdout string 277 stderr string 278 err error 279 } 280 c := make(chan po) 281 go func() { 282 var r po 283 r.stdout, r.stderr, r.err = ExecuteCmd(createReplyCmd(), "--max-messages", "1", v) 284 c <- r 285 }() 286 287 // wait for client 288 ts.WaitForClient(t, "nsc_reply", 1, 60*time.Second) 289 290 // create a conn to the server 291 creds := ts.KeyStore.CalcUserCredsPath("A", "U") 292 nc := ts.CreateClient(t, nats.UserCredentials(creds)) 293 require.NoError(t, nc.Flush()) 294 295 m, err := nc.Request(v, []byte(v), 15*time.Second) 296 require.NoError(t, err) 297 require.Equal(t, v, string(m.Data)) 298 } 299 300 func TestReplyPermissionViolation(t *testing.T) { 301 ts := NewTestStore(t, "O") 302 defer ts.Done(t) 303 ts.AddAccount(t, "A") 304 305 // generate a random subject/payload 306 v := nuid.Next() 307 308 ts.AddUser(t, "A", "U") 309 _, _, err := ExecuteCmd(createEditUserCmd(), "--deny-sub", v) 310 require.NoError(t, err) 311 312 // create the basic configuration 313 conf := filepath.Join(ts.Dir, "server.conf") 314 _, _, err = ExecuteCmd(createServerConfigCmd(), "--mem-resolver", 315 "--config-file", conf) 316 require.NoError(t, err) 317 318 // start a server with the config at a random port 319 ports := ts.RunServerWithConfig(t, conf) 320 321 // with the captured ports, regenerate the operator jwt - we only need the client to update 322 _, _, err = ExecuteCmd(createEditOperatorCmd(), 323 "--service-url", strings.Join(ports.Nats, ",")) 324 require.NoError(t, err) 325 326 _, _, err = ExecuteCmd(createReplyCmd(), "--max-messages", "1", v) 327 require.Error(t, err) 328 require.Contains(t, err.Error(), "Permissions Violation") 329 } 330 331 func Test_EncryptDecrypt(t *testing.T) { 332 ts := NewTestStore(t, "O") 333 defer ts.Done(t) 334 335 k := ts.GetOperatorPublicKey(t) 336 text := "this is a test" 337 et, err := Encrypt(k, []byte(text)) 338 require.NoError(t, err) 339 od, err := Decrypt(k, et) 340 require.NoError(t, err) 341 require.Equal(t, text, string(od)) 342 }