Auth: Able to use API tokens for authentication (#1662)

* Auth: Able to use API tokens for authentication

* Update change log
This commit is contained in:
Alexander Zobnin
2023-07-26 18:23:44 +03:00
committed by GitHub
parent 8205f7aaf8
commit ac976945a5
9 changed files with 174 additions and 55 deletions

View File

@@ -2,6 +2,7 @@ package zabbix
import (
"context"
"errors"
"strings"
"time"
@@ -9,6 +10,7 @@ import (
"github.com/alexanderzobnin/grafana-zabbix/pkg/settings"
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbixapi"
"github.com/bitly/go-simplejson"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
)
@@ -16,11 +18,12 @@ import (
// Zabbix is a wrapper for Zabbix API. It wraps Zabbix API queries and performs authentication, adds caching,
// deduplication and other performance optimizations.
type Zabbix struct {
api *zabbixapi.ZabbixAPI
dsInfo *backend.DataSourceInstanceSettings
cache *ZabbixCache
version int
logger log.Logger
api *zabbixapi.ZabbixAPI
dsInfo *backend.DataSourceInstanceSettings
settings *settings.ZabbixDatasourceSettings
cache *ZabbixCache
version int
logger log.Logger
}
// New returns new instance of Zabbix client.
@@ -29,10 +32,11 @@ func New(dsInfo *backend.DataSourceInstanceSettings, zabbixSettings *settings.Za
zabbixCache := NewZabbixCache(zabbixSettings.CacheTTL, 10*time.Minute)
return &Zabbix{
api: zabbixAPI,
dsInfo: dsInfo,
cache: zabbixCache,
logger: logger,
api: zabbixAPI,
dsInfo: dsInfo,
settings: zabbixSettings,
cache: zabbixCache,
logger: logger,
}, nil
}
@@ -90,11 +94,12 @@ func (zabbix *Zabbix) request(ctx context.Context, method string, params ZabbixA
result, err := zabbix.api.Request(ctx, method, params)
notAuthorized := isNotAuthorized(err)
if err == zabbixapi.ErrNotAuthenticated || notAuthorized {
isTokenAuth := zabbix.settings.AuthType == settings.AuthTypeToken
if err == zabbixapi.ErrNotAuthenticated || (notAuthorized && !isTokenAuth) {
if notAuthorized {
zabbix.logger.Debug("Authentication token expired, performing re-login")
}
err = zabbix.Login(ctx)
err = zabbix.Authenticate(ctx)
if err != nil {
return nil, err
}
@@ -106,12 +111,27 @@ func (zabbix *Zabbix) request(ctx context.Context, method string, params ZabbixA
return result, err
}
func (zabbix *Zabbix) Login(ctx context.Context) error {
func (zabbix *Zabbix) Authenticate(ctx context.Context) error {
jsonData, err := simplejson.NewJson(zabbix.dsInfo.JSONData)
if err != nil {
return err
}
authType := zabbix.settings.AuthType
if authType == settings.AuthTypeToken {
token, exists := zabbix.dsInfo.DecryptedSecureJSONData["apiToken"]
if !exists {
return errors.New("cannot find Zabbix API token")
}
err = zabbix.api.AuthenticateWithToken(ctx, token)
if err != nil {
zabbix.logger.Error("Zabbix authentication error", "error", err)
return err
}
zabbix.logger.Debug("Using API token for authentication")
return nil
}
zabbixLogin := jsonData.Get("username").MustString()
var zabbixPassword string
if securePassword, exists := zabbix.dsInfo.DecryptedSecureJSONData["password"]; exists {

View File

@@ -4,8 +4,9 @@ import (
"context"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/stretchr/testify/assert"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)
var basicDatasourceInfo = &backend.DataSourceInstanceSettings{
@@ -19,7 +20,7 @@ var emptyParams = map[string]interface{}{}
func TestLogin(t *testing.T) {
zabbixClient, _ := MockZabbixClient(basicDatasourceInfo, `{"result":"secretauth"}`, 200)
err := zabbixClient.Login(context.Background())
err := zabbixClient.Authenticate(context.Background())
assert.NoError(t, err)
assert.Equal(t, "secretauth", zabbixClient.api.GetAuth())
@@ -27,7 +28,7 @@ func TestLogin(t *testing.T) {
func TestLoginError(t *testing.T) {
zabbixClient, _ := MockZabbixClient(basicDatasourceInfo, `{"result":""}`, 500)
err := zabbixClient.Login(context.Background())
err := zabbixClient.Authenticate(context.Background())
assert.Error(t, err)
assert.Equal(t, "", zabbixClient.api.GetAuth())