mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Added sentrypeer credentials in config && cache partition
This commit is contained in:
committed by
Dan Christian Bogos
parent
2c1f5012fc
commit
9af02771fd
@@ -55,36 +55,3 @@ func (ban APIBanCfg) Clone() (cln *APIBanCfg) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type SentryPeerCfg struct {
|
||||
Token string
|
||||
Url string
|
||||
}
|
||||
|
||||
func (sp *SentryPeerCfg) loadFromJSONCfg(jsnCfg *SentryPeerJsonCfg) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return
|
||||
}
|
||||
if jsnCfg.Url != nil {
|
||||
sp.Url = *jsnCfg.Url
|
||||
}
|
||||
if jsnCfg.Token != nil {
|
||||
sp.Token = *jsnCfg.Token
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sp *SentryPeerCfg) AsMapInterface() map[string]any {
|
||||
return map[string]any{
|
||||
"URL": sp.Url,
|
||||
"Token": sp.Token,
|
||||
}
|
||||
}
|
||||
|
||||
func (sp *SentryPeerCfg) Clone() (cln *SentryPeerCfg) {
|
||||
cln = &SentryPeerCfg{
|
||||
Url: sp.Url,
|
||||
Token: sp.Token,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -304,6 +304,7 @@ const CGRATES_CFG_JSON = `
|
||||
"*uch": {"limit": -1, "ttl": "3h", "static_ttl": false, "remote":false, "replicate": false}, // User cache
|
||||
"*stir": {"limit": -1, "ttl": "3h", "static_ttl": false, "remote":false, "replicate": false}, // stirShaken cache keys
|
||||
"*apiban":{"limit": -1, "ttl": "2m", "static_ttl": false, "remote":false, "replicate": false},
|
||||
"*sentrypeer":{"limit": -1, "ttl": "86400s", "static_ttl": true, "remote":false, "replicate": false},
|
||||
"*caps_events": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate": false}, // caps cached samples
|
||||
"*replication_hosts": {"limit": 0, "ttl": "", "static_ttl": false, "remote":false, "replicate": false}, // the replication hosts cache(used when replication_filtered is enbled)
|
||||
},
|
||||
@@ -1268,7 +1269,8 @@ const CGRATES_CFG_JSON = `
|
||||
},
|
||||
"sentrypeer":{
|
||||
"url":"",
|
||||
"token":"",
|
||||
"clientID":"",
|
||||
"clientSecret":"",
|
||||
}
|
||||
|
||||
}`
|
||||
|
||||
@@ -877,8 +877,9 @@ type APIBanJsonCfg struct {
|
||||
}
|
||||
|
||||
type SentryPeerJsonCfg struct {
|
||||
Token *string
|
||||
Url *string
|
||||
ClientID *string
|
||||
ClientSecret *string
|
||||
Url *string
|
||||
}
|
||||
|
||||
type CoreSJsonCfg struct {
|
||||
|
||||
58
config/sentrypeer.go
Normal file
58
config/sentrypeer.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
type SentryPeerCfg struct {
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
Url string
|
||||
}
|
||||
|
||||
func (sp *SentryPeerCfg) loadFromJSONCfg(jsnCfg *SentryPeerJsonCfg) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return
|
||||
}
|
||||
if jsnCfg.Url != nil {
|
||||
sp.Url = *jsnCfg.Url
|
||||
}
|
||||
if jsnCfg.ClientSecret != nil {
|
||||
sp.ClientSecret = *jsnCfg.ClientSecret
|
||||
}
|
||||
if jsnCfg.ClientID != nil {
|
||||
sp.ClientID = *jsnCfg.ClientID
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sp *SentryPeerCfg) AsMapInterface() map[string]any {
|
||||
return map[string]any{
|
||||
"URL": sp.Url,
|
||||
"ClientSecret": sp.ClientSecret,
|
||||
"ClientID": sp.ClientID,
|
||||
}
|
||||
}
|
||||
|
||||
func (sp *SentryPeerCfg) Clone() (cln *SentryPeerCfg) {
|
||||
cln = &SentryPeerCfg{
|
||||
Url: sp.Url,
|
||||
ClientSecret: sp.ClientSecret,
|
||||
ClientID: sp.ClientID,
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -111,9 +111,11 @@
|
||||
"apiers_conns": ["*internal"]
|
||||
}
|
||||
|
||||
// "sentrypeer":{
|
||||
// "url":"https://sentrypeer.com/api/",
|
||||
// "token":"put token here",
|
||||
// },
|
||||
//"sentrypeer":{
|
||||
//"url":"https://sentrypeer.com/api/",
|
||||
//"clientID":"",
|
||||
//"clientSecret":"",
|
||||
//},
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -127,9 +127,10 @@
|
||||
"apiers_conns": ["*internal"],
|
||||
},
|
||||
|
||||
//"sentrypeer":{
|
||||
//"url":"https://sentrypeer.com/api/",
|
||||
//"token":""
|
||||
//},
|
||||
// "sentrypeer":{
|
||||
// "url":"https://sentrypeer.com/api/",
|
||||
// "clientID":"",
|
||||
// "clientSecret":"",
|
||||
// },
|
||||
|
||||
}
|
||||
|
||||
@@ -118,9 +118,10 @@
|
||||
"apiers_conns": ["*internal"],
|
||||
},
|
||||
|
||||
// "sentrypeer":{
|
||||
// "url":"https://sentrypeer.com/api/",
|
||||
// "token":"put token here",
|
||||
// },
|
||||
//"sentrypeer":{
|
||||
//"url":"https://sentrypeer.com/api/",
|
||||
//"clientID":"",
|
||||
//"clientSecret":"",
|
||||
//},
|
||||
|
||||
}
|
||||
|
||||
@@ -103,9 +103,10 @@
|
||||
"apiers_conns": ["*internal"],
|
||||
},
|
||||
|
||||
// "sentrypeer":{
|
||||
// "url":"https://sentrypeer.com/api/",
|
||||
// "token":"put token here",
|
||||
// },
|
||||
//"sentrypeer":{
|
||||
//"url":"https://sentrypeer.com/api/",
|
||||
//"clientID":"",
|
||||
//"clientSecret":"",
|
||||
//},
|
||||
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ func (dm *DataManager) CacheDataFromDB(prfx string, ids []string, mustBeCached b
|
||||
case utils.MetaAPIBan:
|
||||
_, err = dm.GetAPIBan(utils.EmptyString, config.CgrConfig().APIBanCfg().Keys, false, false, true)
|
||||
case utils.MetaSentryPeer:
|
||||
_, err = GetSentryPeer(utils.EmptyString, config.CgrConfig().SentryPeerCfg().Url, config.CgrConfig().SentryPeerCfg().Token, utils.EmptyString, false, true)
|
||||
_, err = GetSentryPeer(utils.EmptyString, config.CgrConfig().SentryPeerCfg().Url, config.CgrConfig().SentryPeerCfg().ClientID, config.CgrConfig().SentryPeerCfg().ClientSecret, utils.EmptyString, false, true)
|
||||
}
|
||||
if err != nil {
|
||||
if err != utils.ErrNotFound && err != utils.ErrDSPProfileNotFound && err != utils.ErrDSPHostNotFound {
|
||||
|
||||
@@ -19,7 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
@@ -27,6 +30,10 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type TokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
|
||||
// MatchingItemIDsForEvent returns the list of item IDs matching fieldName/fieldValue for an event
|
||||
// fieldIDs limits the fields which are checked against indexes
|
||||
// helper on top of dataDB.GetIndexes, adding utils.MetaAny to list of fields queried
|
||||
@@ -120,13 +127,51 @@ func WeightFromDynamics(dWs []*utils.DynamicWeight,
|
||||
}
|
||||
return 0.0, nil
|
||||
}
|
||||
|
||||
func GetSentryPeer(val, url, token, path string, cacheRead, cacheWrite bool) (found bool, err error) {
|
||||
func getToken(clientID, clientSecret string, cacheWrite bool, token *TokenResponse) (err error) {
|
||||
var resp *http.Response
|
||||
payload := map[string]string{
|
||||
"client_id": clientID,
|
||||
"client_secret": clientSecret,
|
||||
"audience": "https://sentrypeer.com/api",
|
||||
"grant_type": "client_credentials",
|
||||
}
|
||||
jsonPayload, _ := json.Marshal(payload)
|
||||
resp, err = getHTTP("POST", "https://authz.sentrypeer.com/oauth/token", bytes.NewBuffer(jsonPayload), map[string][]string{"Content-Type": {"application/json"}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
err = json.NewDecoder(resp.Body).Decode(&token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cacheWrite {
|
||||
if err = Cache.Set(utils.MetaSentryPeer, "*token", token.AccessToken, nil, true, utils.NonTransactional); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func GetSentryPeer(val, url, clientID, clientSecret, path string, cacheRead, cacheWrite bool) (found bool, err error) {
|
||||
valpath := utils.ConcatenatedKey(path, val)
|
||||
var (
|
||||
token TokenResponse
|
||||
resp *http.Response
|
||||
cachedReq bool
|
||||
)
|
||||
if cacheRead {
|
||||
if x, ok := Cache.Get(utils.MetaSentryPeer, valpath); ok && x != nil { // Attempt to find in cache first
|
||||
return x.(bool), nil
|
||||
}
|
||||
var cachedToken any
|
||||
if cachedToken, cachedReq = Cache.Get(utils.MetaSentryPeer, "*token"); cachedReq && cachedToken != nil {
|
||||
token.AccessToken = cachedToken.(string)
|
||||
}
|
||||
}
|
||||
if !cachedReq {
|
||||
if err = getToken(clientID, clientSecret, cacheWrite, &token); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
switch path {
|
||||
case "*ip":
|
||||
@@ -134,46 +179,57 @@ func GetSentryPeer(val, url, token, path string, cacheRead, cacheWrite bool) (fo
|
||||
case "*number":
|
||||
url += "phone-numbers/"
|
||||
}
|
||||
var req *http.Request
|
||||
if req, err = http.NewRequest("GET", url+val, nil); err != nil {
|
||||
resp, err = getHTTP("GET", url+val, nil, map[string][]string{"Authorization": {fmt.Sprintf("Bearer %v", token.AccessToken)}})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if token != "" {
|
||||
req.Header = http.Header{
|
||||
"Authorization": {fmt.Sprintf("Bearer %s", token)},
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
|
||||
Cache.Remove(utils.MetaSentryPeer, "*token", true, utils.NonTransactional)
|
||||
utils.Logger.Warning("SentryPeer redirecting to new bearer token ")
|
||||
if err = getToken(clientID, clientSecret, cacheWrite, &token); err != nil {
|
||||
return
|
||||
}
|
||||
resp, err = getHTTP("GET", url+val, nil, map[string][]string{"Authorization": {fmt.Sprintf("Bearer %v", token.AccessToken)}})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
|
||||
return false, fmt.Errorf("still unauthorized after getting new token")
|
||||
}
|
||||
}
|
||||
var resp *http.Response
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||
switch {
|
||||
case resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices:
|
||||
if cacheWrite {
|
||||
if err = Cache.Set(utils.MetaSentryPeer, valpath, false, nil, true, utils.NonTransactional); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
case resp.StatusCode == http.StatusNotFound:
|
||||
if cacheWrite {
|
||||
if err = Cache.Set(utils.MetaSentryPeer, valpath, true, nil, true, utils.NonTransactional); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
} else {
|
||||
switch {
|
||||
case resp.StatusCode == http.StatusNotFound:
|
||||
if cacheWrite {
|
||||
if err = Cache.Set(utils.MetaSentryPeer, valpath, false, nil, true, utils.NonTransactional); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return
|
||||
case resp.StatusCode >= 400 && resp.StatusCode < 500:
|
||||
err = fmt.Errorf("client error<%s>", resp.Status)
|
||||
return
|
||||
case resp.StatusCode >= 500:
|
||||
err = fmt.Errorf("server error<%s>", resp.Status)
|
||||
return
|
||||
default:
|
||||
err = fmt.Errorf("unexpected status code<%s>", resp.Status)
|
||||
}
|
||||
case resp.StatusCode >= http.StatusBadRequest && resp.StatusCode < http.StatusInternalServerError:
|
||||
err = fmt.Errorf("client err <%v>", resp.Status)
|
||||
case resp.StatusCode >= http.StatusInternalServerError:
|
||||
err = fmt.Errorf("server error<%s>", resp.Status)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected status code<%s>", resp.Status)
|
||||
}
|
||||
return
|
||||
utils.Logger.Warning(fmt.Sprintf("Sentrypeer filter got %v ", err.Error()))
|
||||
return false, err
|
||||
}
|
||||
|
||||
func getHTTP(method, url string, payload io.Reader, headers map[string][]string) (resp *http.Response, err error) {
|
||||
var req *http.Request
|
||||
if req, err = http.NewRequest(method, url, payload); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header = headers
|
||||
return http.DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
@@ -659,7 +659,7 @@ func (fltr *FilterRule) passSentryPeer(dDP utils.DataProvider) (bool, error) {
|
||||
if fltr.Values[0] != "*number" && fltr.Values[0] != "*ip" {
|
||||
return false, fmt.Errorf("invalid value for sentrypeer filter: <%s>", fltr.Values[0])
|
||||
}
|
||||
return GetSentryPeer(strVal, config.CgrConfig().SentryPeerCfg().Url, config.CgrConfig().SentryPeerCfg().Token, fltr.Values[0], true, true)
|
||||
return GetSentryPeer(strVal, config.CgrConfig().SentryPeerCfg().Url, config.CgrConfig().SentryPeerCfg().ClientID, config.CgrConfig().SentryPeerCfg().ClientSecret, fltr.Values[0], true, true)
|
||||
}
|
||||
|
||||
func parseTime(rsr *config.RSRParser, dDp utils.DataProvider) (_ time.Time, err error) {
|
||||
|
||||
Reference in New Issue
Block a user