mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-14 20:59:53 +05:00
HttpSkipTlsVerify for http client
This commit is contained in:
@@ -132,7 +132,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
|
||||
}
|
||||
defer fileOut.Close()
|
||||
cdrexp, err := cdre.NewCdrExporter(cdrs, self.LogDb, exportTemplate, exportId,
|
||||
dataUsageMultiplyFactor, costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen)
|
||||
dataUsageMultiplyFactor, costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const (
|
||||
var err error
|
||||
|
||||
func NewCdrExporter(cdrs []*utils.StoredCdr, logDb engine.LogStorage, exportTpl *config.CdreConfig, exportId string,
|
||||
dataUsageMultiplyFactor, costMultiplyFactor float64, costShiftDigits, roundDecimals, cgrPrecision int, maskDestId string, maskLen int) (*CdrExporter, error) {
|
||||
dataUsageMultiplyFactor, costMultiplyFactor float64, costShiftDigits, roundDecimals, cgrPrecision int, maskDestId string, maskLen int, httpSkipTlsCheck bool) (*CdrExporter, error) {
|
||||
if len(cdrs) == 0 { // Nothing to export
|
||||
return nil, nil
|
||||
}
|
||||
@@ -67,6 +67,7 @@ func NewCdrExporter(cdrs []*utils.StoredCdr, logDb engine.LogStorage, exportTpl
|
||||
roundDecimals: roundDecimals,
|
||||
cgrPrecision: cgrPrecision,
|
||||
maskDestId: maskDestId,
|
||||
httpSkipTlsCheck: httpSkipTlsCheck,
|
||||
maskLen: maskLen,
|
||||
negativeExports: make(map[string]string),
|
||||
}
|
||||
@@ -85,6 +86,7 @@ type CdrExporter struct {
|
||||
costShiftDigits, roundDecimals, cgrPrecision int
|
||||
maskDestId string
|
||||
maskLen int
|
||||
httpSkipTlsCheck bool
|
||||
header, trailer []string // Header and Trailer fields
|
||||
content [][]string // Rows of cdr fields
|
||||
firstCdrATime, lastCdrATime time.Time
|
||||
@@ -261,8 +263,12 @@ func (cdre *CdrExporter) processCdr(cdr *utils.StoredCdr) error {
|
||||
case utils.CDRFIELD:
|
||||
outVal, err = cdre.cdrFieldValue(cdr, cfgFld.ValueAsRSRField(), cfgFld.Layout)
|
||||
case HTTP_POST:
|
||||
if outValByte, err := utils.HttpJsonPost(cfgFld.Value, cdr); err == nil {
|
||||
var outValByte []byte
|
||||
if outValByte, err = utils.HttpJsonPost(cfgFld.Value, cdre.httpSkipTlsCheck, cdr); err == nil {
|
||||
outVal = string(outValByte)
|
||||
if len(outVal) == 0 && cfgFld.Mandatory {
|
||||
err = fmt.Errorf("Empty result for http_post field: %s", cfgFld.Name)
|
||||
}
|
||||
}
|
||||
case CONCATENATED_CDRFIELD:
|
||||
for _, fld := range strings.Split(cfgFld.Value, ",") {
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestCsvCdrWriter(t *testing.T) {
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID,
|
||||
ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01,
|
||||
}
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{storedCdr1}, logDb, cfg.CdreDefaultInstance, "firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0)
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{storedCdr1}, logDb, cfg.CdreDefaultInstance, "firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func TestWriteCdr(t *testing.T) {
|
||||
Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 2.34567,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
|
||||
}
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr}, logDb, exportTpl.AsCdreConfig(), "fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1)
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr}, logDb, exportTpl.AsCdreConfig(), "fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -167,7 +167,8 @@ func TestWriteCdrs(t *testing.T) {
|
||||
ExtraFields: map[string]string{"productnumber": "12344", "fieldextr2": "valextr2"},
|
||||
}
|
||||
cfg, _ := config.NewDefaultCGRConfig()
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr1, cdr2, cdr3, cdr4}, logDb, exportTpl.AsCdreConfig(), "fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1)
|
||||
cdre, err := NewCdrExporter([]*utils.StoredCdr{cdr1, cdr2, cdr3, cdr4}, logDb, exportTpl.AsCdreConfig(),
|
||||
"fwv_1", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ type CGRConfig struct {
|
||||
DefaultTenant string // set default tenant
|
||||
DefaultSubject string // set default rating subject, useful in case of fallback
|
||||
RoundingDecimals int // Number of decimals to round end prices at
|
||||
HttpSkipTlsVerify bool // If enabled Http Client will accept any TLS certificate
|
||||
XmlCfgDocument *CgrXmlCfgDocument // Load additional configuration inside xml document
|
||||
RaterEnabled bool // start standalone server (no balancer)
|
||||
RaterBalancer string // balancer address host:port
|
||||
@@ -153,6 +154,7 @@ func (self *CGRConfig) setDefaults() error {
|
||||
self.DefaultTenant = "cgrates.org"
|
||||
self.DefaultSubject = "cgrates"
|
||||
self.RoundingDecimals = 10
|
||||
self.HttpSkipTlsVerify = false
|
||||
self.XmlCfgDocument = nil
|
||||
self.RaterEnabled = false
|
||||
self.RaterBalancer = ""
|
||||
@@ -350,6 +352,9 @@ func loadConfig(c *conf.ConfigFile) (*CGRConfig, error) {
|
||||
if hasOpt = c.HasOption("global", "rounding_decimals"); hasOpt {
|
||||
cfg.RoundingDecimals, _ = c.GetInt("global", "rounding_decimals")
|
||||
}
|
||||
if hasOpt = c.HasOption("global", "http_skip_tls_veify"); hasOpt {
|
||||
cfg.HttpSkipTlsVerify, _ = c.GetBool("global", "http_skip_tls_veify")
|
||||
}
|
||||
// XML config path defined, try loading the document
|
||||
if hasOpt = c.HasOption("global", "xmlcfg_path"); hasOpt {
|
||||
xmlCfgPath, _ := c.GetString("global", "xmlcfg_path")
|
||||
|
||||
@@ -73,6 +73,7 @@ func TestDefaults(t *testing.T) {
|
||||
eCfg.DefaultTenant = "cgrates.org"
|
||||
eCfg.DefaultSubject = "cgrates"
|
||||
eCfg.RoundingDecimals = 10
|
||||
eCfg.HttpSkipTlsVerify = false
|
||||
eCfg.XmlCfgDocument = nil
|
||||
eCfg.RaterEnabled = false
|
||||
eCfg.RaterBalancer = ""
|
||||
@@ -196,6 +197,7 @@ func TestConfigFromFile(t *testing.T) {
|
||||
eCfg.DefaultTenant = "test"
|
||||
eCfg.DefaultSubject = "test"
|
||||
eCfg.RoundingDecimals = 99
|
||||
eCfg.HttpSkipTlsVerify = true
|
||||
eCfg.RaterEnabled = true
|
||||
eCfg.RaterBalancer = "test"
|
||||
eCfg.BalancerEnabled = true
|
||||
|
||||
@@ -29,6 +29,7 @@ default_category = test # Default Type of Record to consider when missing from
|
||||
default_tenant = test # Default Tenant to consider when missing from requests.
|
||||
default_subject = test # Default rating Subject to consider when missing from requests.
|
||||
rounding_decimals = 99 # Number of decimals to round floats/costs at
|
||||
http_skip_tls_veify = true # If enabled Http Client will accept any TLS certificate
|
||||
|
||||
[balancer]
|
||||
enabled = true # Start Balancer service: <true|false>.
|
||||
|
||||
@@ -110,6 +110,20 @@ func TestXmlCdreCfgParseXmlConfig(t *testing.T) {
|
||||
</trailer>
|
||||
</export_template>
|
||||
</configuration>
|
||||
<configuration section="cdre" type="csv" id="CHECK-CSV1">
|
||||
<export_template>
|
||||
<content>
|
||||
<fields>
|
||||
<field name="CGRID" type="cdrfield" value="cgrid" width="40"/>
|
||||
<field name="RatingSubject" type="cdrfield" value="subject" width="24" padding="left" strip="xright" mandatory="true"/>
|
||||
<field name="Usage" type="cdrfield" value="usage" layout="seconds" width="6" padding="right" mandatory="true"/>
|
||||
<field name="AccountReference" type="http_post" value="https://localhost:8000" width="10" strip="xright" padding="left" mandatory="true" />
|
||||
<field name="AccountType" type="http_post" value="https://localhost:8000" width="10" strip="xright" padding="left" mandatory="true" />
|
||||
</fields>
|
||||
</content>
|
||||
</export_template>
|
||||
</configuration>
|
||||
|
||||
</document>`
|
||||
var err error
|
||||
reader := strings.NewReader(cfgXmlStr)
|
||||
@@ -118,7 +132,7 @@ func TestXmlCdreCfgParseXmlConfig(t *testing.T) {
|
||||
} else if cfgDoc == nil {
|
||||
t.Fatal("Could not parse xml configuration document")
|
||||
}
|
||||
if len(cfgDoc.cdres) != 1 {
|
||||
if len(cfgDoc.cdres) != 2 {
|
||||
t.Error("Did not cache")
|
||||
}
|
||||
}
|
||||
@@ -137,6 +151,13 @@ func TestXmlCdreCfgGetCdreCfg(t *testing.T) {
|
||||
if len(cdreFWCfg["CDRE-FW1"].Trailer.Fields) != 9 {
|
||||
t.Error("Unexpected number of trailer fields parsed", len(cdreFWCfg["CDRE-FW1"].Trailer.Fields))
|
||||
}
|
||||
cdreCsvCfg1 := cfgDoc.GetCdreCfgs("CHECK-CSV1")
|
||||
if cdreCsvCfg1 == nil {
|
||||
t.Error("Could not parse CdreFw instance")
|
||||
}
|
||||
if len(cdreCsvCfg1["CHECK-CSV1"].Content.Fields) != 5 {
|
||||
t.Error("Unexpected number of content fields parsed", len(cdreCsvCfg1["CHECK-CSV1"].Content.Fields))
|
||||
}
|
||||
}
|
||||
|
||||
func TestXmlCdreCfgAsCdreConfig(t *testing.T) {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
# default_tenant = cgrates.org # Default Tenant to consider when missing from requests.
|
||||
# default_subject = cgrates # Default rating Subject to consider when missing from requests.
|
||||
# rounding_decimals = 10 # System level precision for floats
|
||||
# http_skip_tls_veify = false # If enabled Http Client will accept any TLS certificate
|
||||
# xmlcfg_path = # Path towards additional config defined in xml file
|
||||
|
||||
[balancer]
|
||||
@@ -53,9 +54,9 @@
|
||||
# cdr_format = csv # Exported CDRs format <csv>
|
||||
# data_usage_multiply_factor = 0.0 # Multiply data usage before export (eg: convert from KBytes to Bytes)
|
||||
# cost_multiply_factor = 0.0 # Multiply cost before export (0.0 to disable), eg: add VAT
|
||||
# cost_rounding_decimals = -1 # Rounding decimals for Cost values. -1 to disable rounding
|
||||
# cost_shift_digits = 0 # Shift digits in the cost on export (eg: convert from EUR to cents)
|
||||
# mask_destination_id = # Destination id containing called addresses to be masked on export
|
||||
# cost_rounding_decimals = -1 # Rounding decimals for Cost values. -1 to disable rounding
|
||||
# cost_shift_digits = 0 # Shift digits in the cost on export (eg: convert from EUR to cents)
|
||||
# mask_destination_id = # Destination id containing called addresses to be masked on export
|
||||
# mask_length = 0 # Length of the destination suffix to be masked
|
||||
# export_dir = /var/log/cgrates/cdre # Path where the exported CDRs will be placed
|
||||
# export_template = cgrid,mediation_runid,tor,accid,reqtype,direction,tenant,category,account,subject,destination,setup_time,answer_time,usage,cost
|
||||
|
||||
@@ -213,7 +213,8 @@ func genericReset(ub *Account) error {
|
||||
}
|
||||
|
||||
func callUrl(ub *Account, a *Action) error {
|
||||
_, err := utils.HttpJsonPost(a.ExtraParameters, ub)
|
||||
cfg := config.CgrConfig()
|
||||
_, err := utils.HttpJsonPost(a.ExtraParameters, cfg.HttpSkipTlsVerify, ub)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -223,9 +224,10 @@ func callUrlAsync(ub *Account, a *Action) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg := config.CgrConfig()
|
||||
go func() {
|
||||
for i := 0; i < 5; i++ { // Loop so we can increase the success rate on best effort
|
||||
if _, err = utils.HttpJsonPost(a.ExtraParameters, ub); err == nil {
|
||||
if _, err = utils.HttpJsonPost(a.ExtraParameters, cfg.HttpSkipTlsVerify, ub); err == nil {
|
||||
break // Success, no need to reinterate
|
||||
} else if i == 4 { // Last iteration, syslog the warning
|
||||
Logger.Warning(fmt.Sprintf("<Triggers> WARNING: Failed calling url: [%s], error: [%s], balance: %s", a.ExtraParameters, err.Error(), ubJson))
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -260,12 +261,16 @@ func AccountAliasKey(tenant, account string) string {
|
||||
return ConcatenatedKey(tenant, account)
|
||||
}
|
||||
|
||||
func HttpJsonPost(url string, content interface{}) ([]byte, error) {
|
||||
func HttpJsonPost(url string, skipTlsVerify bool, content interface{}) ([]byte, error) {
|
||||
body, err := json.Marshal(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.Post(url, "application/json", bytes.NewBuffer(body))
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: skipTlsVerify},
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err := client.Post(url, "application/json", bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestHttpJsonPost(t *testing.T) {
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: DEFAULT_RUNID,
|
||||
Usage: 0.00000001, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
if _, err := HttpJsonPost("http://localhost:8000", cdrOut); err == nil || err.Error() != "Post http://localhost:8000: dial tcp 127.0.0.1:8000: connection refused" {
|
||||
if _, err := HttpJsonPost("http://localhost:8000", false, cdrOut); err == nil || err.Error() != "Post http://localhost:8000: dial tcp 127.0.0.1:8000: connection refused" {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user