The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/serviceaccounts/secretscan/service_test.go

172 lines
4.3 KiB

package secretscan
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/apikey"
)
func TestService_CheckTokens(t *testing.T) {
type testCase struct {
desc string
retrievedTokens []apikey.APIKey
wantHashes []string
leakedTokens []Token
notify bool
revoke bool
}
ctx := context.Background()
falseBool := false
trueBool := true
testCases := []testCase{
{
desc: "no tokens",
retrievedTokens: []apikey.APIKey{},
leakedTokens: []Token{},
notify: false,
revoke: false,
},
{
desc: "one token leaked - no revoke, no notify",
retrievedTokens: []apikey.APIKey{{
ID: 1,
OrgID: 2,
Name: "test",
Key: "test-hash-1",
Role: "Viewer",
Expires: nil,
ServiceAccountId: new(int64),
IsRevoked: &falseBool,
}},
wantHashes: []string{"test-hash-1"},
leakedTokens: []Token{{Hash: "test-hash-1"}},
notify: false,
revoke: false,
},
{
desc: "one token leaked - revoke, no notify",
retrievedTokens: []apikey.APIKey{{
ID: 1,
OrgID: 2,
Name: "test",
Key: "test-hash-1",
Role: "Viewer",
Expires: nil,
ServiceAccountId: new(int64),
IsRevoked: &falseBool,
}},
wantHashes: []string{"test-hash-1"},
leakedTokens: []Token{{Hash: "test-hash-1"}},
notify: false,
revoke: true,
},
{
desc: "two tokens - one revoke, notify",
retrievedTokens: []apikey.APIKey{{
ID: 1,
OrgID: 2,
Name: "test",
Key: "test-hash-1",
Role: "Viewer",
Expires: nil,
ServiceAccountId: new(int64),
IsRevoked: &falseBool,
}, {
ID: 2,
OrgID: 4,
Name: "test-2",
Key: "test-hash-2",
Role: "Viewer",
Expires: nil,
ServiceAccountId: new(int64),
IsRevoked: &falseBool,
}},
wantHashes: []string{"test-hash-1", "test-hash-2"},
leakedTokens: []Token{{Hash: "test-hash-2"}},
notify: true,
revoke: true,
},
{
desc: "one token already revoked should not be checked",
retrievedTokens: []apikey.APIKey{{
ID: 1,
OrgID: 2,
Name: "test",
Key: "test-hash-1",
Role: "Viewer",
Expires: nil,
ServiceAccountId: new(int64),
IsRevoked: &trueBool,
}},
wantHashes: []string{},
leakedTokens: []Token{},
notify: false,
revoke: true,
},
{
desc: "one token expired should not be checked",
retrievedTokens: []apikey.APIKey{{
ID: 1,
OrgID: 2,
Name: "test",
Key: "test-hash-1",
Role: "Viewer",
Expires: new(int64),
ServiceAccountId: new(int64),
IsRevoked: &falseBool,
}},
wantHashes: []string{},
leakedTokens: []Token{},
notify: false,
revoke: true,
},
}
for _, tt := range testCases {
t.Run(tt.desc, func(t *testing.T) {
tokenStore := &MockTokenRetriever{keys: tt.retrievedTokens}
client := &MockSecretScanClient{tokens: tt.leakedTokens}
notifier := &MockSecretScanNotifier{}
service := &Service{
store: tokenStore,
client: client,
webHookClient: notifier,
logger: log.New("secretscan"),
webHookNotify: tt.notify,
revoke: tt.revoke,
}
err := service.CheckTokens(ctx)
require.NoError(t, err)
if len(tt.wantHashes) > 0 {
assert.Equal(t, tt.wantHashes, client.checkCalls[0].([]string))
} else {
assert.Empty(t, client.checkCalls)
}
if len(tt.leakedTokens) > 0 {
if tt.revoke {
assert.Len(t, tokenStore.revokeCalls, len(tt.leakedTokens))
} else {
assert.Empty(t, tokenStore.revokeCalls)
}
}
if tt.notify {
assert.Len(t, notifier.notifyCalls, len(tt.leakedTokens))
} else {
assert.Empty(t, notifier.notifyCalls)
}
})
}
}