HttpSkipTlsVerify for http client

This commit is contained in:
DanB
2014-06-05 11:02:17 +02:00
parent b56356486f
commit f9f994cd7e
12 changed files with 59 additions and 15 deletions

View File

@@ -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())
}

View File

@@ -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, ",") {

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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")

View File

@@ -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

View File

@@ -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>.

View File

@@ -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) {

View File

@@ -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

View File

@@ -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))

View File

@@ -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
}

View File

@@ -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)
}
}