forked from prebid/prebid-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ads.Cert Call Sign support (prebid#2241)
- Loading branch information
1 parent
414adb9
commit 9bfc1ad
Showing
24 changed files
with
1,160 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net/url" | ||
) | ||
|
||
var ( | ||
ErrSignerModeIncorrect = errors.New("signer mode is not specified, specify 'off', 'inprocess' or 'remote'") | ||
ErrInProcessSignerInvalidPrivateKey = errors.New("private key for inprocess signer cannot be empty") | ||
|
||
ErrMsgInProcessSignerInvalidURL = "invalid url for inprocess signer" | ||
ErrMsgInProcessSignerInvalidDNSRenewalInterval = "invalid dns renewal interval for inprocess signer" | ||
ErrMsgInProcessSignerInvalidDNSCheckInterval = "invalid dns check interval for inprocess signer" | ||
ErrMsgInvalidRemoteSignerURL = "invalid url for remote signer" | ||
ErrMsgInvalidRemoteSignerSigningTimeout = "invalid signing timeout for remote signer" | ||
) | ||
|
||
const ( | ||
AdCertsSignerModeOff = "off" | ||
AdCertsSignerModeInprocess = "inprocess" | ||
AdCertsSignerModeRemote = "remote" | ||
) | ||
|
||
// Experiment defines if experimental features are available | ||
type Experiment struct { | ||
AdCerts ExperimentAdsCert `mapstructure:"adscert"` | ||
} | ||
|
||
// ExperimentAdsCert configures and enables functionality to generate and send Ads Cert Auth header to bidders | ||
type ExperimentAdsCert struct { | ||
Mode string `mapstructure:"mode"` | ||
InProcess AdsCertInProcess `mapstructure:"inprocess"` | ||
Remote AdsCertRemote `mapstructure:"remote"` | ||
} | ||
|
||
// AdsCertInProcess configures data to sign requests using ads certs library in core PBS logic | ||
type AdsCertInProcess struct { | ||
// Origin is ads.cert hostname for the originating party | ||
Origin string `mapstructure:"origin"` | ||
// PrivateKey is a base-64 encoded private key. | ||
PrivateKey string `mapstructure:"key"` | ||
// DNSCheckIntervalInSeconds specifies frequency to check origin _delivery._adscert and _adscert subdomains, used for indexing data, default: 30 | ||
DNSCheckIntervalInSeconds int `mapstructure:"domain_check_interval_seconds"` | ||
// DNSRenewalIntervalInSeconds specifies frequency to renew origin _delivery._adscert and _adscert subdomains, used for indexing data, default: 30 | ||
DNSRenewalIntervalInSeconds int `mapstructure:"domain_renewal_interval_seconds"` | ||
} | ||
|
||
// AdsCertRemote configures data to sign requests using remote signatory service | ||
type AdsCertRemote struct { | ||
// Url is the address of gRPC server that will create a call signature | ||
Url string `mapstructure:"url"` | ||
// SigningTimeoutMs specifies how long this client will wait for signing to finish before abandoning | ||
SigningTimeoutMs int `mapstructure:"signing_timeout_ms"` | ||
} | ||
|
||
func (cfg *Experiment) validate(errs []error) []error { | ||
if len(cfg.AdCerts.Mode) == 0 { | ||
return errs | ||
} | ||
if !(cfg.AdCerts.Mode == AdCertsSignerModeOff || | ||
cfg.AdCerts.Mode == AdCertsSignerModeInprocess || | ||
cfg.AdCerts.Mode == AdCertsSignerModeRemote) { | ||
return append(errs, ErrSignerModeIncorrect) | ||
} | ||
if cfg.AdCerts.Mode == AdCertsSignerModeInprocess { | ||
_, err := url.ParseRequestURI(cfg.AdCerts.InProcess.Origin) | ||
if err != nil { | ||
errs = append(errs, fmt.Errorf("%s: %s", ErrMsgInProcessSignerInvalidURL, cfg.AdCerts.InProcess.Origin)) | ||
} | ||
if len(cfg.AdCerts.InProcess.PrivateKey) == 0 { | ||
errs = append(errs, ErrInProcessSignerInvalidPrivateKey) | ||
} | ||
if cfg.AdCerts.InProcess.DNSRenewalIntervalInSeconds <= 0 { | ||
errs = append(errs, fmt.Errorf("%s: %d", ErrMsgInProcessSignerInvalidDNSRenewalInterval, cfg.AdCerts.InProcess.DNSRenewalIntervalInSeconds)) | ||
} | ||
if cfg.AdCerts.InProcess.DNSCheckIntervalInSeconds <= 0 { | ||
errs = append(errs, fmt.Errorf("%s: %d", ErrMsgInProcessSignerInvalidDNSCheckInterval, cfg.AdCerts.InProcess.DNSCheckIntervalInSeconds)) | ||
} | ||
} else if cfg.AdCerts.Mode == AdCertsSignerModeRemote { | ||
_, err := url.ParseRequestURI(cfg.AdCerts.Remote.Url) | ||
if err != nil { | ||
errs = append(errs, fmt.Errorf("%s: %s", ErrMsgInvalidRemoteSignerURL, cfg.AdCerts.Remote.Url)) | ||
} | ||
if cfg.AdCerts.Remote.SigningTimeoutMs <= 0 { | ||
errs = append(errs, fmt.Errorf("%s: %d", ErrMsgInvalidRemoteSignerSigningTimeout, cfg.AdCerts.Remote.SigningTimeoutMs)) | ||
} | ||
} | ||
return errs | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestExperimentValidate(t *testing.T) { | ||
testCases := []struct { | ||
desc string | ||
data Experiment | ||
expectErrors bool | ||
expectedErrors []error | ||
}{ | ||
{ | ||
desc: "Remote signer config: invalid remote url passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeRemote, Remote: AdsCertRemote{Url: "test@com", SigningTimeoutMs: 5}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{errors.New("invalid url for remote signer: test@com")}, | ||
}, | ||
{ | ||
desc: "Remote signer config: invalid SigningTimeoutMs passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeRemote, Remote: AdsCertRemote{Url: "http://test.com", SigningTimeoutMs: 0}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{errors.New("invalid signing timeout for remote signer: 0")}, | ||
}, | ||
{ | ||
desc: "Remote signer config: invalid URL and SigningTimeoutMs passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeRemote, Remote: AdsCertRemote{Url: "test@com", SigningTimeoutMs: 0}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{errors.New("invalid url for remote signer: test@com"), | ||
errors.New("invalid signing timeout for remote signer: 0")}, | ||
}, | ||
{ | ||
desc: "Remote signer config: valid URL and SigningTimeoutMs passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeRemote, Remote: AdsCertRemote{Url: "http://test.com", SigningTimeoutMs: 5}}, | ||
}, | ||
expectErrors: false, | ||
expectedErrors: []error{}, | ||
}, | ||
{ | ||
desc: "Experiment config: experiment config is empty", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: ""}, | ||
}, | ||
expectErrors: false, | ||
expectedErrors: []error{}, | ||
}, | ||
{ | ||
desc: "Experiment config: experiment config is off", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeOff}, | ||
}, | ||
expectErrors: false, | ||
expectedErrors: []error{}, | ||
}, | ||
{ | ||
desc: "Experiment config: experiment config is init with a wrong value", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: "test"}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{ErrSignerModeIncorrect}, | ||
}, | ||
{ | ||
desc: "Inprocess signer config: valid config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeInprocess, InProcess: AdsCertInProcess{Origin: "http://test.com", PrivateKey: "pk", DNSCheckIntervalInSeconds: 10, DNSRenewalIntervalInSeconds: 10}}, | ||
}, | ||
expectErrors: false, | ||
expectedErrors: []error{}, | ||
}, | ||
{ | ||
desc: "Inprocess signer config: invaild origin url passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeInprocess, InProcess: AdsCertInProcess{Origin: "test@com", PrivateKey: "pk", DNSCheckIntervalInSeconds: 10, DNSRenewalIntervalInSeconds: 10}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{errors.New("invalid url for inprocess signer: test@com")}, | ||
}, | ||
{ | ||
desc: "Inprocess signer config: empty PK passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeInprocess, InProcess: AdsCertInProcess{Origin: "http://test.com", PrivateKey: "", DNSCheckIntervalInSeconds: 10, DNSRenewalIntervalInSeconds: 10}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{ErrInProcessSignerInvalidPrivateKey}, | ||
}, | ||
{ | ||
desc: "Inprocess signer config: negative dns check interval passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeInprocess, InProcess: AdsCertInProcess{Origin: "http://test.com", PrivateKey: "pk", DNSCheckIntervalInSeconds: -10, DNSRenewalIntervalInSeconds: 10}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{errors.New("invalid dns check interval for inprocess signer: -10")}, | ||
}, | ||
{ | ||
desc: "Inprocess signer config: zero dns check interval passed to config", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeInprocess, InProcess: AdsCertInProcess{Origin: "http://test.com", PrivateKey: "pk", DNSCheckIntervalInSeconds: 10, DNSRenewalIntervalInSeconds: 0}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{errors.New("invalid dns renewal interval for inprocess signer: 0")}, | ||
}, | ||
{ | ||
desc: "Inprocess signer config: all config parameters are invalid", | ||
data: Experiment{ | ||
AdCerts: ExperimentAdsCert{Mode: AdCertsSignerModeInprocess, InProcess: AdsCertInProcess{Origin: "test@com", PrivateKey: "", DNSCheckIntervalInSeconds: -10, DNSRenewalIntervalInSeconds: 0}}, | ||
}, | ||
expectErrors: true, | ||
expectedErrors: []error{ | ||
errors.New("invalid url for inprocess signer: test@com"), | ||
ErrInProcessSignerInvalidPrivateKey, | ||
errors.New("invalid dns check interval for inprocess signer: -10"), | ||
errors.New("invalid dns renewal interval for inprocess signer: 0")}, | ||
}, | ||
} | ||
for _, test := range testCases { | ||
errs := test.data.validate([]error{}) | ||
if test.expectErrors { | ||
assert.ElementsMatch(t, test.expectedErrors, errs, "Test case threw unexpected errors. Desc: %s \n", test.desc) | ||
} else { | ||
assert.Empty(t, test.expectedErrors, "Test case should not return errors. Desc: %s \n", test.desc) | ||
} | ||
} | ||
} |
Oops, something went wrong.