Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ads.Cert Call Sign support #2241

Merged
merged 46 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
1312664
Initial preparation for Ads.Cert Call Sign support
May 6, 2022
1722b81
First initial working version
May 10, 2022
384bb22
Added request option and bidder config to enable or disable ads certs
May 23, 2022
a94d723
Code clean up and README file added
May 24, 2022
1547a0b
Code refactoring and clean up
May 25, 2022
7f91db7
Unit tests fix
May 25, 2022
3e6f780
Merge branch 'master' into ads_cert
May 25, 2022
82715a9
Merge fixes
May 25, 2022
9c28dd6
Code refactoring and clean up
May 26, 2022
0bc246d
Added more go docs for newly defines structures
May 26, 2022
aea4f71
Added unit tests
May 26, 2022
9bffd99
Added unit tests
May 26, 2022
b8baa68
Added unit tests
May 27, 2022
ac47bd5
Minor clean up
May 28, 2022
c78b16d
Added remote signer.
May 29, 2022
540c9f8
Removed optional code
Jun 1, 2022
26dac9b
Added tests for NewAdCertsSigner
Jun 1, 2022
de1d8fa
Unit tests for remote signer
Jun 2, 2022
4b9e937
CR fixes part I
Jun 2, 2022
7b6ffe9
CR fixes part II
Jun 3, 2022
8991f4e
Code clean up
Jun 8, 2022
6257437
Merge branch 'master' into ads_cert
Jun 8, 2022
6f87497
Merge fixes
Jun 8, 2022
a091df9
Merge branch 'master' into ads_cert
Jun 22, 2022
1e012b0
renamed "in-process" to "inprocess" to avoid env variables conflict
Jun 23, 2022
8b3a795
Renamed adscert to adsCert
Jun 23, 2022
4462439
Code refactoring
Jun 23, 2022
8b0617b
Code refactoring and signers config validation
Jun 24, 2022
f0ac967
Code refactoring
Jun 24, 2022
bb4c9d9
Code refactoring
Jun 24, 2022
cea7973
Merge branch 'master' into ads_cert
Jun 30, 2022
1636dd3
Resolved merge errors
Jun 30, 2022
2d29975
Merge branch 'master' into ads_cert
Jul 5, 2022
37d2529
Merge with master
Jul 5, 2022
2178fc6
Code review comments
Jul 8, 2022
8709b76
Merge branch 'master' into ads_cert
Jul 11, 2022
72cae9b
Merge conflict fix
Jul 11, 2022
7486973
Moved validation to config.go
Jul 11, 2022
a1177a9
Minor fixes
Jul 13, 2022
d3d50bb
Modified config from experiment.adscert.enabled to experiment.adscert…
Jul 13, 2022
a92f723
Merge branch 'master' into ads_cert
Jul 18, 2022
999e6da
Code review fixes
Jul 19, 2022
d0a9966
Code review fixes
Jul 19, 2022
b9fc196
Code review fixes
Jul 20, 2022
5b81715
Code cleanup
Jul 27, 2022
c3c0fc2
Code cleanup
Jul 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Code refactoring
  • Loading branch information
vsolovei committed Jun 23, 2022
commit 446243904e87f17af0ee28ab80eaec50e6780cda
9 changes: 8 additions & 1 deletion config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ func TestDefaults(t *testing.T) {
cmpStrings(t, "stored_requests.filesystem.directorypath", "./stored_requests/data/by_id", cfg.StoredRequests.Files.Path)
cmpBools(t, "auto_gen_source_tid", cfg.AutoGenSourceTID, true)
cmpBools(t, "generate_bid_id", cfg.GenerateBidID, false)
cmpBools(t, "experiment.adscert.enabled", cfg.Experiment.AdCerts.Enabled, false)
cmpStrings(t, "experiment.adscert.inprocess.origin", cfg.Experiment.AdCerts.InProcess.Origin, "")
cmpStrings(t, "experiment.adscert.inprocess.key", cfg.Experiment.AdCerts.InProcess.PrivateKey, "")
cmpInts(t, "experiment.adscert.inprocess.domain_check_interval_seconds", cfg.Experiment.AdCerts.InProcess.DNSCheckIntervalInSeconds, 30)
cmpInts(t, "experiment.adscert.inprocess.domain_renewal_interval_seconds", cfg.Experiment.AdCerts.InProcess.DNSRenewalIntervalInSeconds, 30)
cmpStrings(t, "experiment.adscert.remote.url", cfg.Experiment.AdCerts.Remote.Url, "")
cmpInts(t, "experiment.adscert.remote.signing_timeout_ms", cfg.Experiment.AdCerts.Remote.SigningTimeoutMs, 5)

//Assert purpose VendorExceptionMap hash tables were built correctly
expectedTCF2 := TCF2{
Expand Down Expand Up @@ -379,7 +386,7 @@ generate_bid_id: true
experiment:
adscert:
enabled: true
in-process:
inprocess:
origin: "test.com"
key: "ABC123"
domain_check_interval_seconds: 40
Expand Down
2 changes: 1 addition & 1 deletion config/experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type AdsCertInProcess struct {

// AdsCertRemote configures data to sign requests using remote signatory service
type AdsCertRemote struct {
//Url - address of grpc server
//Url - 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"`
Expand Down
2 changes: 1 addition & 1 deletion docs/adscertsigner.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Host config, can be set using env variables or yaml config, use proper format:
}
```
####Remote signer
To use this approach stanalone GRPC server should be available.
To use this approach standalone GRPC server should be available.
One way to do this is to run in locally. For this checkout [AdsCert OSS](https://github.com/IABTechLab/adscert) and navigate to https://github.com/IABTechLab/adscert/blob/main/cmd/server/main.go file.
Modify L17, set "origin" to `adscertdelivery.com`, make sure ports 3000 and 3001 are available and run main function.
In Prebid Server configs set parameters for this server:
Expand Down
9 changes: 6 additions & 3 deletions exchange/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type AdaptedBidder interface {
//
// Any errors will be user-facing in the API.
// Error messages should help publishers understand what might account for "bad" bids.
requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error)
requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error)
}

//bidRequestOptions holds additional options for bid request execution to maintain clean code and reasonable number of parameters
Expand Down Expand Up @@ -142,7 +142,7 @@ type bidderAdapterConfig struct {
DebugInfo config.DebugInfo
}

func (bidder *bidderAdapter) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error) {
func (bidder *bidderAdapter) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error) {

var reqData []*adapters.RequestData
var errs []error
Expand Down Expand Up @@ -173,7 +173,10 @@ func (bidder *bidderAdapter) requestBid(ctx context.Context, bidderRequest Bidde
reqData[i].Headers.Add("Sec-GPC", reqInfo.GlobalPrivacyControlHeader)
}
if bidRequestMetadata.addCallSignHeader {
signatureMessage, err := adCertSigner.Sign(reqData[i].Uri, reqData[i].Body)
signatureMessage, err := adsCertSigner.Sign(reqData[i].Uri, reqData[i].Body)
if err != nil {
//add metrics here
}
if err == nil && len(signatureMessage) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add appropriate error handling for when error is not nil

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea here is to record this to log or metrics. This will be added in separate PR. I don't think we want to discard the entire request if header was not generated properly. Added a comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding a comment. Are there any requirements to add a warning in response when debug is enabled to let the publisher know that there was a problem signing the request? If so, is the plan to add that as part of a later PR as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a warning back to the publisher/caller is a good idea. I think a separate PR would be appropriate. This is getting close to the end of review and is already large enough.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate PR sounds good to me 👍 @VeronikaSolovei9 would you mind just modifying the comment to add a warning message in debug mode as well in addition to the metrics please? Just so that we don't forget about it

reqData[i].Headers.Add(adscert.SignHeader, signatureMessage)
}
Expand Down
4 changes: 2 additions & 2 deletions exchange/bidder_validate_bids.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ type validatedBidder struct {
bidder AdaptedBidder
}

func (v *validatedBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error) {
seatBid, errs := v.bidder.requestBid(ctx, bidderRequest, bidAdjustment, conversions, reqInfo, adCertSigner, bidRequestMetadata)
func (v *validatedBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error) {
seatBid, errs := v.bidder.requestBid(ctx, bidderRequest, bidAdjustment, conversions, reqInfo, adsCertSigner, bidRequestMetadata)
if validationErrors := removeInvalidBids(bidderRequest.BidRequest, seatBid); len(validationErrors) > 0 {
errs = append(errs, validationErrors...)
}
Expand Down
2 changes: 1 addition & 1 deletion exchange/bidder_validate_bids_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,6 @@ type mockAdaptedBidder struct {
errorResponse []error
}

func (b *mockAdaptedBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error) {
func (b *mockAdaptedBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (*pbsOrtbSeatBid, []error) {
return b.bidResponse, b.errorResponse
}
12 changes: 6 additions & 6 deletions exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ type exchange struct {
privacyConfig config.Privacy
categoriesFetcher stored_requests.CategoryFetcher
bidIDGenerator BidIDGenerator
adCertSigner adscert.Signer
adsCertSigner adscert.Signer
}

// Container to pass out response ext data from the GetAllBids goroutines back into the main thread
Expand Down Expand Up @@ -113,7 +113,7 @@ func (randomDeduplicateBidBooleanGenerator) Generate() bool {
return rand.Intn(100) < 50
}

func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid_cache_client.Client, cfg *config.Configuration, syncersByBidder map[string]usersync.Syncer, metricsEngine metrics.MetricsEngine, infos config.BidderInfos, gdprPermsBuilder gdpr.PermissionsBuilder, tcf2CfgBuilder gdpr.TCF2ConfigBuilder, currencyConverter *currency.RateConverter, categoriesFetcher stored_requests.CategoryFetcher, adCertSigner adscert.Signer) Exchange {
func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid_cache_client.Client, cfg *config.Configuration, syncersByBidder map[string]usersync.Syncer, metricsEngine metrics.MetricsEngine, infos config.BidderInfos, gdprPermsBuilder gdpr.PermissionsBuilder, tcf2CfgBuilder gdpr.TCF2ConfigBuilder, currencyConverter *currency.RateConverter, categoriesFetcher stored_requests.CategoryFetcher, adsCertSigner adscert.Signer) Exchange {
bidderToSyncerKey := map[string]string{}
for bidder, syncer := range syncersByBidder {
bidderToSyncerKey[bidder] = syncer.Key()
Expand Down Expand Up @@ -143,7 +143,7 @@ func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid
LMT: cfg.LMT,
},
bidIDGenerator: &bidIDGenerator{cfg.GenerateBidID},
adCertSigner: adCertSigner,
adsCertSigner: adsCertSigner,
}
}

Expand Down Expand Up @@ -520,9 +520,9 @@ func (e *exchange) getAllBids(
bidReqOptions := bidRequestOptions{
accountDebugAllowed: accountDebugAllowed,
headerDebugAllowed: headerDebugAllowed,
addCallSignHeader: callSignHeader(experiment, e.bidderInfo[string(bidderRequest.BidderName)]),
addCallSignHeader: isAdsCertEnabled(experiment, e.bidderInfo[string(bidderRequest.BidderName)]),
}
bids, err := e.adapterMap[bidderRequest.BidderCoreName].requestBid(ctx, bidderRequest, adjustmentFactor, conversions, &reqInfo, e.adCertSigner, bidReqOptions)
bids, err := e.adapterMap[bidderRequest.BidderCoreName].requestBid(ctx, bidderRequest, adjustmentFactor, conversions, &reqInfo, e.adsCertSigner, bidReqOptions)

// Add in time reporting
elapsed := time.Since(start)
Expand Down Expand Up @@ -1195,7 +1195,7 @@ func buildStoredAuctionResponse(storedAuctionResponses map[string]json.RawMessag
return adapterBids, liveAdapters, nil
}

func callSignHeader(experiment *openrtb_ext.Experiment, info config.BidderInfo) bool {
func isAdsCertEnabled(experiment *openrtb_ext.Experiment, info config.BidderInfo) bool {
requestAdsCertEnabled := experiment != nil && experiment.AdsCert != nil && experiment.AdsCert.Enabled
bidderAdsCertEnabled := info.Experiment.AdsCert.Enable
return requestAdsCertEnabled && bidderAdsCertEnabled
Expand Down
8 changes: 4 additions & 4 deletions exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4173,7 +4173,7 @@ func TestCallSignHeader(t *testing.T) {
},
}
for _, test := range testCases {
result := callSignHeader(&test.experiment, test.bidderInfo)
result := isAdsCertEnabled(&test.experiment, test.bidderInfo)
assert.Equal(t, test.expectedResult, result, "incorrect result returned")
}

Expand Down Expand Up @@ -4266,7 +4266,7 @@ type validatingBidder struct {
mockResponses map[string]bidderResponse
}

func (b *validatingBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (seatBid *pbsOrtbSeatBid, errs []error) {
func (b *validatingBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (seatBid *pbsOrtbSeatBid, errs []error) {
if expectedRequest, ok := b.expectations[string(bidderRequest.BidderName)]; ok {
if expectedRequest != nil {
if expectedRequest.BidAdjustment != bidAdjustment {
Expand Down Expand Up @@ -4314,7 +4314,7 @@ type capturingRequestBidder struct {
req *openrtb2.BidRequest
}

func (b *capturingRequestBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (seatBid *pbsOrtbSeatBid, errs []error) {
func (b *capturingRequestBidder) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (seatBid *pbsOrtbSeatBid, errs []error) {
b.req = bidderRequest.BidRequest
return &pbsOrtbSeatBid{}, nil
}
Expand Down Expand Up @@ -4416,7 +4416,7 @@ func (e *emptyUsersync) HasAnyLiveSyncs() bool {

type panicingAdapter struct{}

func (panicingAdapter) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (posb *pbsOrtbSeatBid, errs []error) {
func (panicingAdapter) requestBid(ctx context.Context, bidderRequest BidderRequest, bidAdjustment float64, conversions currency.Conversions, reqInfo *adapters.ExtraRequestInfo, adsCertSigner adscert.Signer, bidRequestMetadata bidRequestOptions) (posb *pbsOrtbSeatBid, errs []error) {
panic("Panic! Panic! The world is ending!")
}

Expand Down
2 changes: 2 additions & 0 deletions experiment/adscert/inprocesssigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import (
"time"
)

// inProcessSigner - holds the signatory to add adsCert header to requests using in process go library
type inProcessSigner struct {
signatory signatory.AuthenticatedConnectionsSignatory
}

mansinahar marked this conversation as resolved.
Show resolved Hide resolved
// Sign - adds adsCert header to requests using in process go library
func (ips *inProcessSigner) Sign(destinationURL string, body []byte) (string, error) {
req := &api.AuthenticatedConnectionSignatureRequest{
RequestInfo: createRequestInfo(destinationURL, body),
Expand Down
4 changes: 3 additions & 1 deletion experiment/adscert/remotesigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (
"time"
)

// remoteSigner - holds the signatory to add adsCert header to requests using remote signing server
SyntaxNode marked this conversation as resolved.
Show resolved Hide resolved
type remoteSigner struct {
signatory signatory.AuthenticatedConnectionsSignatory
}

// Sign - adds adsCert header to requests using remote signing server
func (rs *remoteSigner) Sign(destinationURL string, body []byte) (string, error) {
// The RequestInfo proto contains details about the individual ad request
// being signed. A SetRequestInfo helper function derives a hash of the
Expand All @@ -29,7 +31,7 @@ func (rs *remoteSigner) Sign(destinationURL string, body []byte) (string, error)
if err != nil {
return "", err
}
if signatureResponse != nil && signatureResponse.SignatureOperationStatus == api.SignatureOperationStatus_SIGNATURE_OPERATION_STATUS_OK {
if signatureResponse.GetSignatureOperationStatus() == api.SignatureOperationStatus_SIGNATURE_OPERATION_STATUS_OK {
signatureMessage := signatureResponse.RequestInfo.SignatureInfo[0].SignatureMessage
return signatureMessage, err
}
Expand Down
4 changes: 2 additions & 2 deletions router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,12 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R
errs := errortypes.NewAggregateError("Failed to initialize adapters", adaptersErrs)
return nil, errs
}
adCertSigner, err := adscert.NewAdCertsSigner(cfg.Experiment.AdCerts)
adsCertSigner, err := adscert.NewAdCertsSigner(cfg.Experiment.AdCerts)
if err != nil {
glog.Fatalf("Failed to create ads cert signer: %v", err)
}

theExchange := exchange.NewExchange(adapters, cacheClient, cfg, syncersByBidder, r.MetricsEngine, bidderInfos, gdprPermsBuilder, tcf2CfgBuilder, rateConvertor, categoriesFetcher, adCertSigner)
theExchange := exchange.NewExchange(adapters, cacheClient, cfg, syncersByBidder, r.MetricsEngine, bidderInfos, gdprPermsBuilder, tcf2CfgBuilder, rateConvertor, categoriesFetcher, adsCertSigner)
var uuidGenerator uuidutil.UUIDRandomGenerator
openrtbEndpoint, err := openrtb2.NewEndpoint(uuidGenerator, theExchange, paramsValidator, fetcher, accounts, cfg, r.MetricsEngine, pbsAnalytics, disabledBidders, defReqJSON, activeBidders, storedRespFetcher)
if err != nil {
Expand Down