github.com/nats-io/nsc@v0.0.0-20221206222106-35db9400b257/cmd/revokeactivation_test.go (about)

     1  /*
     2   * Copyright 2018-2020 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  	"testing"
    20  	"time"
    21  
    22  	"github.com/nats-io/jwt/v2"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  func TestRevokeActivation(t *testing.T) {
    27  	ts := NewTestStore(t, "revoke_clear_user")
    28  	defer ts.Done(t)
    29  
    30  	ts.AddAccount(t, "A")
    31  	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
    32  	ts.AddExport(t, "A", jwt.Service, "bar", false)
    33  	ts.AddExport(t, "A", jwt.Service, "public", true) // we support revoking public exports
    34  
    35  	_, pub, _ := CreateAccountKey(t)
    36  
    37  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--subject", "foo.bar", "--target-account", pub)
    38  	require.NoError(t, err)
    39  
    40  	_, _, err = ExecuteCmd(createRevokeActivationCmd(), "--subject", "bar", "--target-account", pub, "--service")
    41  	require.NoError(t, err)
    42  
    43  	_, _, err = ExecuteCmd(createRevokeActivationCmd(), "--subject", "public", "--target-account", pub, "--service")
    44  	require.NoError(t, err)
    45  
    46  	ac, err := ts.Store.ReadAccountClaim("A")
    47  	require.NoError(t, err)
    48  	require.Len(t, ac.Exports, 3)
    49  
    50  	for _, exp := range ac.Exports {
    51  		require.True(t, exp.Revocations.IsRevoked(pub, time.Unix(0, 0)))
    52  	}
    53  }
    54  
    55  func TestRevokeActivationAt(t *testing.T) {
    56  	ts := NewTestStore(t, "test")
    57  	defer ts.Done(t)
    58  
    59  	ts.AddAccount(t, "A")
    60  	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
    61  	ts.AddExport(t, "A", jwt.Service, "bar", false)
    62  
    63  	_, pub, _ := CreateAccountKey(t)
    64  
    65  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--subject", "foo.bar", "--target-account", pub, "--at", "1000")
    66  	require.NoError(t, err)
    67  
    68  	_, _, err = ExecuteCmd(createRevokeActivationCmd(), "--subject", "bar", "--target-account", pub, "--service", "--at", "1000")
    69  	require.NoError(t, err)
    70  
    71  	ac, err := ts.Store.ReadAccountClaim("A")
    72  	require.NoError(t, err)
    73  	require.Len(t, ac.Exports, 2)
    74  
    75  	for _, exp := range ac.Exports {
    76  		require.True(t, exp.Revocations.IsRevoked(pub, time.Unix(999, 0)))
    77  		require.False(t, exp.Revocations.IsRevoked(pub, time.Unix(1001, 0)))
    78  	}
    79  }
    80  
    81  func TestRevokeActivationForStreamInteractive(t *testing.T) {
    82  	ts := NewTestStore(t, "test")
    83  	defer ts.Done(t)
    84  
    85  	ts.AddAccount(t, "A")
    86  	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
    87  	ts.AddExport(t, "A", jwt.Service, "bar", false)
    88  	ts.AddAccount(t, "B")
    89  	ts.AddExport(t, "B", jwt.Stream, "foo.>", false)
    90  	ts.AddExport(t, "B", jwt.Service, "bar", false)
    91  
    92  	_, pub, _ := CreateAccountKey(t)
    93  
    94  	input := []interface{}{1, false, 0, pub, "1000"} // second account "B"
    95  	cmd := createRevokeActivationCmd()
    96  	HoistRootFlags(cmd)
    97  	_, _, err := ExecuteInteractiveCmd(cmd, input, "-i")
    98  	require.NoError(t, err)
    99  
   100  	ac, err := ts.Store.ReadAccountClaim("A")
   101  	require.NoError(t, err)
   102  
   103  	for _, exp := range ac.Exports {
   104  		require.Len(t, exp.Revocations, 0)
   105  	}
   106  
   107  	ac, err = ts.Store.ReadAccountClaim("B")
   108  	require.NoError(t, err)
   109  
   110  	for _, exp := range ac.Exports {
   111  		if exp.Subject != "foo.>" {
   112  			require.Len(t, exp.Revocations, 0)
   113  			continue
   114  		}
   115  		require.Len(t, exp.Revocations, 1)
   116  		require.True(t, exp.Revocations.IsRevoked(pub, time.Unix(999, 0)))
   117  		require.False(t, exp.Revocations.IsRevoked(pub, time.Unix(1001, 0)))
   118  	}
   119  }
   120  
   121  func TestRevokeActivationForServiceInteractive(t *testing.T) {
   122  	ts := NewTestStore(t, "test")
   123  	defer ts.Done(t)
   124  
   125  	ts.AddAccount(t, "A")
   126  	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
   127  	ts.AddExport(t, "A", jwt.Service, "bar", false)
   128  	ts.AddAccount(t, "B")
   129  	ts.AddExport(t, "B", jwt.Stream, "foo.>", false)
   130  	ts.AddExport(t, "B", jwt.Service, "bar", false)
   131  
   132  	_, pub, _ := CreateAccountKey(t)
   133  
   134  	input := []interface{}{1, true, 0, pub, "1000"} // second account "B"
   135  	cmd := createRevokeActivationCmd()
   136  	HoistRootFlags(cmd)
   137  	_, _, err := ExecuteInteractiveCmd(cmd, input, "-i")
   138  	require.NoError(t, err)
   139  
   140  	ac, err := ts.Store.ReadAccountClaim("A")
   141  	require.NoError(t, err)
   142  
   143  	for _, exp := range ac.Exports {
   144  		require.Len(t, exp.Revocations, 0)
   145  	}
   146  
   147  	ac, err = ts.Store.ReadAccountClaim("B")
   148  	require.NoError(t, err)
   149  
   150  	for _, exp := range ac.Exports {
   151  		if exp.Subject != "bar" {
   152  			require.Len(t, exp.Revocations, 0)
   153  			continue
   154  		}
   155  		require.Len(t, exp.Revocations, 1)
   156  		require.True(t, exp.Revocations.IsRevoked(pub, time.Unix(999, 0)))
   157  		require.False(t, exp.Revocations.IsRevoked(pub, time.Unix(1001, 0)))
   158  	}
   159  }
   160  
   161  func TestRevokeActivationNoExports(t *testing.T) {
   162  	ts := NewTestStore(t, "O")
   163  	defer ts.Done(t)
   164  	ts.AddAccount(t, "A")
   165  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*")
   166  	require.Error(t, err)
   167  	require.Contains(t, err.Error(), "doesn't have exports")
   168  }
   169  
   170  func TestRevokeActivationServiceNoExports(t *testing.T) {
   171  	ts := NewTestStore(t, "O")
   172  	defer ts.Done(t)
   173  	ts.AddAccount(t, "A")
   174  	ts.AddExport(t, "A", jwt.Service, "q", false)
   175  
   176  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*")
   177  	require.Error(t, err)
   178  	require.Contains(t, err.Error(), "doesn't have stream exports")
   179  }
   180  
   181  func TestRevokeActivationStreamNoExports(t *testing.T) {
   182  	ts := NewTestStore(t, "O")
   183  	defer ts.Done(t)
   184  	ts.AddAccount(t, "A")
   185  	ts.AddExport(t, "A", jwt.Stream, "q", false)
   186  
   187  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service")
   188  	require.Error(t, err)
   189  	require.Contains(t, err.Error(), "doesn't have service exports")
   190  }
   191  
   192  func TestRevokeActivationSubjectRequired(t *testing.T) {
   193  	ts := NewTestStore(t, "O")
   194  	defer ts.Done(t)
   195  	ts.AddAccount(t, "A")
   196  	ts.AddExport(t, "A", jwt.Service, "q", false)
   197  	ts.AddExport(t, "A", jwt.Service, "qq", false)
   198  
   199  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service")
   200  	require.Error(t, err)
   201  	require.Contains(t, err.Error(), "a subject is required")
   202  }
   203  
   204  func TestRevokeActivationExportNotFound(t *testing.T) {
   205  	ts := NewTestStore(t, "O")
   206  	defer ts.Done(t)
   207  	ts.AddAccount(t, "A")
   208  	ts.AddExport(t, "A", jwt.Service, "q", false)
   209  
   210  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service", "--subject", "foo")
   211  	require.Error(t, err)
   212  	require.Contains(t, err.Error(), "unable to locate export")
   213  }
   214  
   215  func TestRevokeActivationDefaultSubject(t *testing.T) {
   216  	ts := NewTestStore(t, "O")
   217  	defer ts.Done(t)
   218  	ts.AddAccount(t, "A")
   219  	ts.AddExport(t, "A", jwt.Service, "q", false)
   220  
   221  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service")
   222  	require.NoError(t, err)
   223  }
   224  
   225  func TestRevokeActivationAll(t *testing.T) {
   226  	ts := NewTestStore(t, "O")
   227  	defer ts.Done(t)
   228  	ts.AddAccount(t, "A")
   229  	ts.AddExport(t, "A", jwt.Service, "q", false)
   230  
   231  	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service", "--subject", "q")
   232  	require.NoError(t, err)
   233  }
   234  
   235  func TestRevokeActivationBadInteractiveAt(t *testing.T) {
   236  	ts := NewTestStore(t, "O")
   237  	defer ts.Done(t)
   238  	ts.AddAccount(t, "A")
   239  	ts.AddExport(t, "A", jwt.Service, "q", false)
   240  
   241  	input := []interface{}{true, 0, "*", "hello"}
   242  	_, _, err := ExecuteInteractiveCmd(createRevokeActivationCmd(), input)
   243  	require.Error(t, err)
   244  	require.Contains(t, err.Error(), `provided value "hello" is not`)
   245  }