From f8e6a084cb549701ffb177b912953869b5fdd702 Mon Sep 17 00:00:00 2001 From: Atlantis Bot Date: Wed, 20 Mar 2024 13:40:22 -0500 Subject: [PATCH 01/10] Manage Backstage metadata by Terraform https://github.com/LiveRamp/infrastructure/pull/33151 --- catalog-info.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 catalog-info.yaml diff --git a/catalog-info.yaml b/catalog-info.yaml new file mode 100644 index 0000000..88369e9 --- /dev/null +++ b/catalog-info.yaml @@ -0,0 +1,12 @@ +# BEGIN TERRAFORM MANAGED BLOCK +"apiVersion": "backstage.io/v1alpha1" +"kind": "Location" +"metadata": + "annotations": + "github.com/project-slug": "LiveRamp/iabconsent" + "github.com/team-slug": "LiveRamp/ps" + "description": "A Go implementation of the IAB Consent String Specs (v1.1 and v2)" + "name": "iabconsent" + "tags": [] +"spec": {} +# END TERRAFORM MANAGED BLOCK From fbbee12d15cd162d8209431f967aa4ede2263fa6 Mon Sep 17 00:00:00 2001 From: Disha Patel <137230863+pateldisha09@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:22:32 -0400 Subject: [PATCH 02/10] [PXS-2412] Add GPP strings for additional states (#32) * GPP strings for additional states * consent fixture test for florida * change field type for TX * add TODO for test cases * remove dummy test FL * remove dummy test FL * adding support for DE, IA, NE, NH, NJ, TN * remove similar fields ProcessingNotice & AdditionalDataProcessingConsent * more consent fixtures for FL, MT, OR * comments, fix consent fixtures for FL, MT, OR * consent fixture for TX * consent fixtures for DE, IA, NE, NH, NJ, TN * more test fixtures for all the states * comments * comments --------- Co-authored-by: Disha Patel --- gpp_parsed_consent.go | 10 + gpp_parsed_consent_fixture_test.go | 32 +- mspa_parsed_consent.go | 3 + mspa_parsed_consent_fixture_test.go | 612 ++++++++++++++++++++++++++++ mspa_parsed_consent_test.go | 50 +++ mspa_sections.go | 479 ++++++++++++++++++++++ 6 files changed, 1185 insertions(+), 1 deletion(-) diff --git a/gpp_parsed_consent.go b/gpp_parsed_consent.go index 8114abf..1836468 100644 --- a/gpp_parsed_consent.go +++ b/gpp_parsed_consent.go @@ -15,6 +15,16 @@ const ( UsColoradoSID UsUtahSID UsConnecticutSID + UsFloridaSID + UsMontanaSID + UsOregonSID + UsTexasSID + UsDelawareSID + UsIowaSID + UsNebraskaSID + UsNewHampshireSID + UsNewJerseySID + UsTennesseeSID ) // GppHeader is the first section of a GPP Consent String. diff --git a/gpp_parsed_consent_fixture_test.go b/gpp_parsed_consent_fixture_test.go index 56d5ede..19a08ab 100644 --- a/gpp_parsed_consent_fixture_test.go +++ b/gpp_parsed_consent_fixture_test.go @@ -5,7 +5,6 @@ import ( ) // Test fixtures can be created here: https://iabgpp.com/ - var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ // Valid GPP w/ US National MSPA, No Subsection (is thesame as false GPC subsection. "DBABLA~BVVqAAEABCA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]}, @@ -37,9 +36,40 @@ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"], iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"], }, + // Valid GPP w/ US US National, California MSPA, Virgina MSPA, Colorado MSPA, Utah MSPA, Conneticut MSPA, Florida MSPA and Montana MSPA Subsection of GPC False. + "DBABrWA~BVVqAAEABCA~BVoYYZoI~BVoYYYI~BVoYYQg~BVaGGGCA~BVoYYYQg~Bqqqqqqo~Bqqqqqqo": { + iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"], + iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"], + iabconsent.UsVirginiaSID: mspaConsentFixtures[iabconsent.UsVirginiaSID]["BVoYYYI"], + iabconsent.UsColoradoSID: mspaConsentFixtures[iabconsent.UsColoradoSID]["BVoYYQg"], + iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"], + iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"], + iabconsent.UsFloridaSID: mspaConsentFixtures[iabconsent.UsFloridaSID]["Bqqqqqqo"], + iabconsent.UsMontanaSID: mspaConsentFixtures[iabconsent.UsMontanaSID]["Bqqqqqqo"], + }, // Valid GPP string w/ sections for EU TCF V2 and US Privacy // Since both are not supported, Consent fixture should be blank. "DBACNY~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN": {}, // Valid GPP w/ US National MSPA and US Privacy, but skip US Privacy until supported. "DBABzw~1YNN~BVVqAAEABCA.QA": {7: mspaConsentFixtures[7]["BVVqAAEABCA.QA"]}, + // Valid GPP w/ US Florida MSPA, Subsection of GPC False. + "DBABAw~Bqqqqqqo": {iabconsent.UsFloridaSID: mspaConsentFixtures[iabconsent.UsFloridaSID]["Bqqqqqqo"]}, + // Valid GPP w/ US Montana MSPA, Subsection of GPC False. + "DBABQw~Bqqqqqqo": {iabconsent.UsMontanaSID: mspaConsentFixtures[iabconsent.UsMontanaSID]["Bqqqqqqo"]}, + // Valid GPP w/ US Oregon MSPA, Subsection of GPC False. + "DBABIw~BqqqqqqqoA": {iabconsent.UsOregonSID: mspaConsentFixtures[iabconsent.UsOregonSID]["BqqqqqqqoA"]}, + // Valid GPP w/ US Texas MSPA, Subsection of GPC False. + "DBABEw~BqqqqqqA": {iabconsent.UsTexasSID: mspaConsentFixtures[iabconsent.UsTexasSID]["BqqqqqqA"]}, + // Valid GPP w/ US Delaware MSPA, Subsection of GPC False. + "DBABUw~BqqqqqqqoA": {iabconsent.UsDelawareSID: mspaConsentFixtures[iabconsent.UsDelawareSID]["BqqqqqqqoA"]}, + // Valid GPP w/ US Iowa MSPA, Subsection of GPC False. + "DBABCw~BVVVVVVA": {iabconsent.UsIowaSID: mspaConsentFixtures[iabconsent.UsIowaSID]["BVVVVVVA"]}, + // Valid GPP w/ US Nebraska MSPA, Subsection of GPC False. + "DBABSw~BmaqqqqA": {iabconsent.UsNebraskaSID: mspaConsentFixtures[iabconsent.UsNebraskaSID]["BmaqqqqA"]}, + // Valid GPP w/ US New Hampshire MSPA, Subsection of GPC False. + "DBABKw~Bpmqqqqo": {iabconsent.UsNewHampshireSID: mspaConsentFixtures[iabconsent.UsNewHampshireSID]["Bpmqqqqo"]}, + // Valid GPP w/ US New Jersey MSPA, Subsection of GPC False. + "DBABAYA~BlWqqqmaqA": {iabconsent.UsNewJerseySID: mspaConsentFixtures[iabconsent.UsNewJerseySID]["BlWqqqmaqA"]}, + // Valid GPP w/ US Tennessee MSPA, Subsection of GPC False. + "DBABQYA~Bqqqqqo": {iabconsent.UsTennesseeSID: mspaConsentFixtures[iabconsent.UsTennesseeSID]["Bqqqqqo"]}, } diff --git a/mspa_parsed_consent.go b/mspa_parsed_consent.go index 5f3f892..004583f 100644 --- a/mspa_parsed_consent.go +++ b/mspa_parsed_consent.go @@ -9,6 +9,7 @@ type MspaParsedConsent struct { // 0 Not Applicable. The Business does not share Personal Data with Third Parties. // 1 Yes, notice was provided // 2 No, notice was not provided + // Note: ProcessingNotice and SharingNotice are the same SharingNotice MspaNotice // Notice of the Opportunity to Opt Out of the Sale of the Consumer’s Personal Data. // 0 Not Applicable. The Business does not Sell Personal Data. @@ -29,6 +30,7 @@ type MspaParsedConsent struct { // 0 Not Applicable. The Business does not Process Sensitive Data. // 1 Yes, notice was provided // 2 No, notice was not provided + // Note: SensitiveDataOptOutNotice and SensitiveDataProcessingOptOutNotice are the same SensitiveDataProcessingOptOutNotice MspaNotice // Notice of the Opportunity to Limit Use or Disclosure of the Consumer’s Sensitive Data. // 0 Not Applicable. The Business does not use or disclose Sensitive Data. @@ -72,6 +74,7 @@ type MspaParsedConsent struct { // 0 Not Applicable. The Business does not use, retain, Sell, or Share the Consumer’s Personal Data for advertising purposes that are unrelated to or incompatible with the purpose(s) for which the Consumer’s Personal Data was collected or processed. // 1 No Consent // 2 Consent + // Note: AdditionalDataProcessingConsent and PersonalDataConsents are the same PersonalDataConsents MspaConsent // Publisher or Advertiser, as applicable, is a signatory to the IAB Multistate Service Provider Agreement (MSPA), as may be amended from time to time, and declares that the transaction is a “Covered Transaction” as defined in the MSPA. // 1 Yes diff --git a/mspa_parsed_consent_fixture_test.go b/mspa_parsed_consent_fixture_test.go index a3177df..f0f1cc4 100644 --- a/mspa_parsed_consent_fixture_test.go +++ b/mspa_parsed_consent_fixture_test.go @@ -404,4 +404,616 @@ var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ Gpc: true, }, }, + // Florida + iabconsent.UsFloridaSID: { + // usfl with subsection of GPC False. + "Bqqqqqqo": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usfl with subsection of GPC True. + "Bqqqqqqo.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // Montana + iabconsent.UsMontanaSID: { + // usmt with subsection of GPC False. + "Bqqqqqqo": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usmt with subsection of GPC True. + "Bqqqqqqo.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // Oregon + iabconsent.UsOregonSID: { + // usor with subsection of GPC False. + "BqqqqqqqoA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + 8: iabconsent.Consent, + 9: iabconsent.Consent, + 10: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usor with subsection of GPC True. + "BqqqqqqqoA.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + 8: iabconsent.Consent, + 9: iabconsent.Consent, + 10: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // Texas + iabconsent.UsTexasSID: { + // ustx with subsection of GPC False. + "BqqqqqqA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // ustx with subsection of GPC True. + "BqqqqqqA.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // Delaware + iabconsent.UsDelawareSID: { + // usde with subsection of GPC False. + "BqqqqqqqoA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + 8: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usde with subsection of GPC True. + "BqqqqqqqoA.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + 8: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // Iowa + iabconsent.UsIowaSID: { + // usia with subsection of GPC False + "BVVVVVVA": { + Version: 1, + SharingNotice: iabconsent.NoticeProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SensitiveDataProcessingOptOutNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.NoConsent, + 1: iabconsent.NoConsent, + 2: iabconsent.NoConsent, + 3: iabconsent.NoConsent, + 4: iabconsent.NoConsent, + 5: iabconsent.NoConsent, + 6: iabconsent.NoConsent, + 7: iabconsent.NoConsent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.NoConsent, + }, + MspaCoveredTransaction: iabconsent.MspaYes, + MspaOptOutOptionMode: iabconsent.MspaYes, + MspaServiceProviderMode: iabconsent.MspaYes, + Gpc: false, + }, + // usia with subsection of GPC True + "BVVVVVVA.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SensitiveDataProcessingOptOutNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.NoConsent, + 1: iabconsent.NoConsent, + 2: iabconsent.NoConsent, + 3: iabconsent.NoConsent, + 4: iabconsent.NoConsent, + 5: iabconsent.NoConsent, + 6: iabconsent.NoConsent, + 7: iabconsent.NoConsent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.NoConsent, + }, + MspaCoveredTransaction: iabconsent.MspaYes, + MspaOptOutOptionMode: iabconsent.MspaYes, + MspaServiceProviderMode: iabconsent.MspaYes, + Gpc: true, + }, + }, + // Nebraska + iabconsent.UsNebraskaSID: { + // usne with subsection of GPC False + "BmaqqqqA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usne with subsection of GPC True + "BmaqqqqA.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // New Hampshire + iabconsent.UsNewHampshireSID: { + // usnh with subsection of GPC False + "Bpmqqqqo": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usnh with subsection of GPC True + "Bpmqqqqo.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // New Jersey + iabconsent.UsNewJerseySID: { + // usnj with subsection of GPC False + "BlWqqqmaqA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + 8: iabconsent.Consent, + 9: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.NoConsent, + 2: iabconsent.Consent, + 3: iabconsent.NoConsent, + 4: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // usnj with subsection of GPC True + "BlWqqqmaqA.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + 8: iabconsent.Consent, + 9: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.NoConsent, + 2: iabconsent.Consent, + 3: iabconsent.NoConsent, + 4: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaCoveredTransaction: iabconsent.MspaNo, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, + // Tennessee + iabconsent.UsTennesseeSID: { + // ustn with subsection of GPC False + "Bqqqqqo": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: false, + }, + // ustn with subsection of GPC True + "Bqqqqqo.YA": { + Version: 1, + SharingNotice: iabconsent.NoticeNotProvided, + SaleOptOutNotice: iabconsent.NoticeNotProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeNotProvided, + SaleOptOut: iabconsent.NotOptedOut, + TargetedAdvertisingOptOut: iabconsent.NotOptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + 1: iabconsent.Consent, + 2: iabconsent.Consent, + 3: iabconsent.Consent, + 4: iabconsent.Consent, + 5: iabconsent.Consent, + 6: iabconsent.Consent, + 7: iabconsent.Consent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.Consent, + }, + PersonalDataConsents: iabconsent.Consent, + MspaOptOutOptionMode: iabconsent.MspaNo, + MspaServiceProviderMode: iabconsent.MspaNo, + Gpc: true, + }, + }, } diff --git a/mspa_parsed_consent_test.go b/mspa_parsed_consent_test.go index b4eedc7..e790cf8 100644 --- a/mspa_parsed_consent_test.go +++ b/mspa_parsed_consent_test.go @@ -157,6 +157,56 @@ func (s *MspaSuite) TestParseMSPAError(c *check.C) { key: "usct", sid: iabconsent.UsConnecticutSID, }, + { + desc: "Florida", + key: "usfl", + sid: iabconsent.UsFloridaSID, + }, + { + desc: "Montana", + key: "usmt", + sid: iabconsent.UsMontanaSID, + }, + { + desc: "Oregon", + key: "usor", + sid: iabconsent.UsOregonSID, + }, + { + desc: "Texas", + key: "ustx", + sid: iabconsent.UsTexasSID, + }, + { + desc: "Delaware", + key: "usde", + sid: iabconsent.UsDelawareSID, + }, + { + desc: "Iowa", + key: "usia", + sid: iabconsent.UsIowaSID, + }, + { + desc: "Nebraska", + key: "usne", + sid: iabconsent.UsNebraskaSID, + }, + { + desc: "New Hampshire", + key: "usnh", + sid: iabconsent.UsNewHampshireSID, + }, + { + desc: "New Jersey", + key: "usnj", + sid: iabconsent.UsNewJerseySID, + }, + { + desc: "Tennessee", + key: "ustn", + sid: iabconsent.UsTennesseeSID, + }, } var tcs = []struct { desc string diff --git a/mspa_sections.go b/mspa_sections.go index 689e7cc..35821d5 100644 --- a/mspa_sections.go +++ b/mspa_sections.go @@ -31,6 +31,46 @@ type MspaUsCT struct { GppSection } +type MspaUsFL struct { + GppSection +} + +type MspaUsMT struct { + GppSection +} + +type MspaUsOR struct { + GppSection +} + +type MspaUsTX struct { + GppSection +} + +type MspaUsDE struct { + GppSection +} + +type MspaUsIA struct { + GppSection +} + +type MspaUsNE struct { + GppSection +} + +type MspaUsNH struct { + GppSection +} + +type MspaUsNJ struct { + GppSection +} + +type MspaUsTN struct { + GppSection +} + // NewMspa returns a supported parser given a GPP Section ID. // If the SID is not yet supported, it will be null. func NewMspa(sid int, section string) GppSectionParser { @@ -47,6 +87,26 @@ func NewMspa(sid int, section string) GppSectionParser { return &MspaUsUT{GppSection{sectionId: UsUtahSID, sectionValue: section}} case UsConnecticutSID: return &MspaUsCT{GppSection{sectionId: UsConnecticutSID, sectionValue: section}} + case UsFloridaSID: + return &MspaUsFL{GppSection{sectionId: UsFloridaSID, sectionValue: section}} + case UsMontanaSID: + return &MspaUsMT{GppSection{sectionId: UsMontanaSID, sectionValue: section}} + case UsOregonSID: + return &MspaUsOR{GppSection{sectionId: UsOregonSID, sectionValue: section}} + case UsTexasSID: + return &MspaUsTX{GppSection{sectionId: UsTexasSID, sectionValue: section}} + case UsDelawareSID: + return &MspaUsDE{GppSection{sectionId: UsDelawareSID, sectionValue: section}} + case UsIowaSID: + return &MspaUsIA{GppSection{sectionId: UsIowaSID, sectionValue: section}} + case UsNebraskaSID: + return &MspaUsNE{GppSection{sectionId: UsNebraskaSID, sectionValue: section}} + case UsNewHampshireSID: + return &MspaUsNH{GppSection{sectionId: UsNewHampshireSID, sectionValue: section}} + case UsNewJerseySID: + return &MspaUsNJ{GppSection{sectionId: UsNewJerseySID, sectionValue: section}} + case UsTennesseeSID: + return &MspaUsTN{GppSection{sectionId: UsTennesseeSID, sectionValue: section}} } // Skip if no matching struct, as Section ID is not supported yet. // Any newly supported Section IDs should be added as cases here. @@ -312,3 +372,422 @@ func (m *MspaUsCT) ParseConsent() (GppParsedConsent, error) { return p, r.Err } + +func (m *MspaUsFL) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usfl consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/FL + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(3) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + // 0 is not a valid value according to the docs for MspaCoveredTransaction. Instead of erroring, + // return the value of the string, and let downstream processing handle if the value is 0. + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsMT) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usmt consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/MT + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(3) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + // 0 is not a valid value according to the docs for MspaCoveredTransaction. Instead of erroring, + // return the value of the string, and let downstream processing handle if the value is 0. + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsOR) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usor consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/OR + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(11) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(3) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + // 0 is not a valid value according to the docs for MspaCoveredTransaction. Instead of erroring, + // return the value of the string, and let downstream processing handle if the value is 0. + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsTX) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse ustx consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/TX + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(1) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + // 0 is not a valid value according to the docs for MspaCoveredTransaction. Instead of erroring, + // return the value of the string, and let downstream processing handle if the value is 0. + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsDE) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usde consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/DE + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(9) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(5) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + // 0 is not a valid value according to the docs for MspaCoveredTransaction. Instead of erroring, + // return the value of the string, and let downstream processing handle if the value is 0. + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsIA) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usia consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/IA + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SensitiveDataProcessingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(1) + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsNE) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usne consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/NE + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(1) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsNH) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usnh consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/NH + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(3) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsNJ) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse usnj consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/NJ + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(10) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(5) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} + +func (m *MspaUsTN) ParseConsent() (GppParsedConsent, error) { + var segments = strings.Split(m.sectionValue, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse ustn consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-States/TN + var p = &MspaParsedConsent{} + p.Version, _ = r.ReadInt(6) + + if p.Version != 1 { + return nil, errors.New("non-v1 string passed.") + } + + p.SharingNotice, _ = r.ReadMspaNotice() + p.SaleOptOutNotice, _ = r.ReadMspaNotice() + p.TargetedAdvertisingOptOutNotice, _ = r.ReadMspaNotice() + p.SaleOptOut, _ = r.ReadMspaOptOut() + p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(1) + p.PersonalDataConsents, _ = r.ReadMspaConsent() + p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() + p.MspaServiceProviderMode, _ = r.ReadMspaNaYesNo() + + if len(segments) > 1 { + var gppSubsectionConsent *GppSubSection + gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + p.Gpc = gppSubsectionConsent.Gpc + } + + return p, r.Err +} From 3408f0fa47349c7154a7a8ad24586dda2c8415ff Mon Sep 17 00:00:00 2001 From: Kyle Halverson Date: Wed, 23 Oct 2024 11:27:00 -0400 Subject: [PATCH 03/10] [SPIKE] Handle Subsection Errors (#34) * check for error in subsection when parsing, and continue not adding that gpp section in that case. tests for bad gpc subsection. * remove unused test case var, and fix comment. --- .gitignore | 1 + gpp_parsed_consent_fixture_test.go | 2 +- gpp_parsed_consent_test.go | 91 +++++++++++++++++++++--------- mspa_sections.go | 80 ++++++++++++++++++++------ 4 files changed, 130 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index 57872d0..0dca145 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /vendor/ +.idea diff --git a/gpp_parsed_consent_fixture_test.go b/gpp_parsed_consent_fixture_test.go index 19a08ab..cb3aea1 100644 --- a/gpp_parsed_consent_fixture_test.go +++ b/gpp_parsed_consent_fixture_test.go @@ -6,7 +6,7 @@ import ( // Test fixtures can be created here: https://iabgpp.com/ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ - // Valid GPP w/ US National MSPA, No Subsection (is thesame as false GPC subsection. + // Valid GPP w/ US National MSPA, No Subsection (is the same as false GPC subsection). "DBABLA~BVVqAAEABCA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]}, // Valid GPP w/ US National MSPA, Subsection of GPC False. "DBABLA~BVVqAAEABCA.QA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]}, diff --git a/gpp_parsed_consent_test.go b/gpp_parsed_consent_test.go index 22b53d7..2f2dec0 100644 --- a/gpp_parsed_consent_test.go +++ b/gpp_parsed_consent_test.go @@ -128,23 +128,7 @@ func (s *MspaSuite) TestMapGppSectionToParser(c *check.C) { } } -func (s *MspaSuite) TestParseGppConsent(c *check.C) { - for g, e := range gppParsedConsentFixtures { - c.Log(g) - - var p, err = iabconsent.ParseGppConsent(g) - - c.Check(err, check.IsNil) - c.Check(p, check.HasLen, len(e)) - for i, expected := range e { - parsed, found := p[i] - c.Check(found, check.Equals, true) - c.Check(parsed, check.DeepEquals, expected) - } - } -} - -func (s *MspaSuite) TestParseGppErrors(c *check.C) { +func (s *MspaSuite) TestMapGppSectionToParserErrors(c *check.C) { tcs := []struct { desc string gpp string @@ -176,17 +160,59 @@ func (s *MspaSuite) TestParseGppErrors(c *check.C) { } } +func (s *MspaSuite) TestParseGppConsent(c *check.C) { + for g, e := range gppParsedConsentFixtures { + c.Log(g) + + var p, err = iabconsent.ParseGppConsent(g) + + c.Check(err, check.IsNil) + c.Check(p, check.HasLen, len(e)) + for i, expected := range e { + parsed, found := p[i] + c.Check(found, check.Equals, true) + c.Check(parsed, check.DeepEquals, expected) + } + } +} + +func (s *MspaSuite) TestParseGppConsentError(c *check.C) { + tcs := []struct { + desc string + gpp string + }{ + { + desc: "Empty Subsection.", + gpp: "DBABzw~1YNN~BVVqAAEABCA.", + }, + { + desc: "Empty Subsection.", + gpp: "DBABAw~Bqqqqqqo.", + }, + } + for _, tc := range tcs { + c.Log(tc.desc) + + var p, err = iabconsent.ParseGppConsent(tc.gpp) + + // Despite an error in the underlying parsing, we quietly do not add the bad value to the map. + c.Check(err, check.IsNil) + c.Check(p, check.HasLen, 0) + } +} + func (s *GppParseSuite) TestParseGppSubSections(c *check.C) { var tcs = []struct { - description string - subsections string - expected *iabconsent.GppSubSection + description string + subsections string + expectedSubsection *iabconsent.GppSubSection + expectedError error }{ { description: "GPC Type, false value", // 01000000 subsections: "QA", - expected: &iabconsent.GppSubSection{ + expectedSubsection: &iabconsent.GppSubSection{ Gpc: false, }, }, @@ -194,7 +220,7 @@ func (s *GppParseSuite) TestParseGppSubSections(c *check.C) { description: "GPC Type, true value.", // 01100000 subsections: "YA", - expected: &iabconsent.GppSubSection{ + expectedSubsection: &iabconsent.GppSubSection{ Gpc: true, }, }, @@ -202,7 +228,7 @@ func (s *GppParseSuite) TestParseGppSubSections(c *check.C) { description: "No GPC Type.", // 00000000 subsections: "AA", - expected: &iabconsent.GppSubSection{ + expectedSubsection: &iabconsent.GppSubSection{ Gpc: false, }, }, @@ -210,7 +236,7 @@ func (s *GppParseSuite) TestParseGppSubSections(c *check.C) { description: "GPC True, then GPC False, should remain True.", // 01100000.01000000 subsections: "YA.QA", - expected: &iabconsent.GppSubSection{ + expectedSubsection: &iabconsent.GppSubSection{ Gpc: true, }, }, @@ -218,10 +244,17 @@ func (s *GppParseSuite) TestParseGppSubSections(c *check.C) { description: "GPC False, then GPC True, should remain True.", // 01000000.01100000 subsections: "QA.YA", - expected: &iabconsent.GppSubSection{ + expectedSubsection: &iabconsent.GppSubSection{ Gpc: true, }, }, + { + description: "GPC Error.", + // Blank value + subsections: "", + expectedSubsection: nil, + expectedError: errors.New("parse gpp subsection type: read int: read bits (index=0, length=2): bits: index out of range"), + }, } for _, tc := range tcs { @@ -229,8 +262,12 @@ func (s *GppParseSuite) TestParseGppSubSections(c *check.C) { // There may be >1 subsections, and func expects them as an array, so split. subsect := strings.Split(tc.subsections, ".") var g, err = iabconsent.ParseGppSubSections(subsect) - c.Check(err, check.IsNil) - c.Check(g, check.DeepEquals, tc.expected) + if tc.expectedError == nil { + c.Check(err, check.IsNil) + } else { + c.Check(err.Error(), check.Equals, tc.expectedError.Error()) + } + c.Check(g, check.DeepEquals, tc.expectedSubsection) } } diff --git a/mspa_sections.go b/mspa_sections.go index 35821d5..08f7cdf 100644 --- a/mspa_sections.go +++ b/mspa_sections.go @@ -153,7 +153,10 @@ func (m *MspaUsNational) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -197,7 +200,10 @@ func (m *MspaUsCA) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -239,7 +245,10 @@ func (m *MspaUsVA) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -281,7 +290,10 @@ func (m *MspaUsCO) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -324,7 +336,10 @@ func (m *MspaUsUT) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -366,7 +381,10 @@ func (m *MspaUsCT) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -409,7 +427,10 @@ func (m *MspaUsFL) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -452,7 +473,10 @@ func (m *MspaUsMT) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -495,7 +519,10 @@ func (m *MspaUsOR) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -538,7 +565,10 @@ func (m *MspaUsTX) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -581,7 +611,10 @@ func (m *MspaUsDE) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -622,7 +655,10 @@ func (m *MspaUsIA) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -663,7 +699,10 @@ func (m *MspaUsNE) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -704,7 +743,10 @@ func (m *MspaUsNH) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -745,7 +787,10 @@ func (m *MspaUsNJ) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } @@ -785,7 +830,10 @@ func (m *MspaUsTN) ParseConsent() (GppParsedConsent, error) { if len(segments) > 1 { var gppSubsectionConsent *GppSubSection - gppSubsectionConsent, _ = ParseGppSubSections(segments[1:]) + gppSubsectionConsent, err = ParseGppSubSections(segments[1:]) + if err != nil { + return p, err + } p.Gpc = gppSubsectionConsent.Gpc } From 5e973206de8d2ea3e4818a7ed7e71aceff35f280 Mon Sep 17 00:00:00 2001 From: Atlantis Bot Date: Thu, 24 Oct 2024 10:39:09 -0400 Subject: [PATCH 04/10] Manage Backstage metadata by Terraform https://github.com/LiveRamp/infrastructure/pull/38204 From 61144699297c1dca2ea1b1142e0b2c21dd2e31e6 Mon Sep 17 00:00:00 2001 From: Atlantis Bot Date: Tue, 20 May 2025 11:10:01 -0400 Subject: [PATCH 05/10] Manage Backstage metadata by Terraform https://github.com/LiveRamp/infrastructure/pull/42756 From 82d6075764b62e752ad692165d755f57c5bc3063 Mon Sep 17 00:00:00 2001 From: Atlantis Bot Date: Wed, 28 May 2025 18:58:37 -0400 Subject: [PATCH 06/10] Manage Backstage metadata by Terraform https://github.com/LiveRamp/infrastructure/pull/43079 --- catalog-info.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/catalog-info.yaml b/catalog-info.yaml index 88369e9..547230b 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -8,5 +8,4 @@ "description": "A Go implementation of the IAB Consent String Specs (v1.1 and v2)" "name": "iabconsent" "tags": [] -"spec": {} # END TERRAFORM MANAGED BLOCK From aea8117381359c248b4001f04f07509206865b18 Mon Sep 17 00:00:00 2001 From: Snyk Service Account Date: Wed, 28 May 2025 19:00:32 -0400 Subject: [PATCH 07/10] Manage Snyk Org metadata by Terraform https://github.com/LiveRamp/infrastructure/pull/43079 --- .snyk.d/import.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .snyk.d/import.yaml diff --git a/.snyk.d/import.yaml b/.snyk.d/import.yaml new file mode 100644 index 0000000..ad8d391 --- /dev/null +++ b/.snyk.d/import.yaml @@ -0,0 +1,4 @@ +# BEGIN TERRAFORM MANAGED BLOCK +"orgName": "ps" +"schema": 2 +# END TERRAFORM MANAGED BLOCK From ca9299df75242b9ed1e98600ccf7810b535e1cf6 Mon Sep 17 00:00:00 2001 From: Joseph Kosten <52718375+jwkosten@users.noreply.github.com> Date: Wed, 4 Jun 2025 08:28:09 -0700 Subject: [PATCH 08/10] [PXS-2689] US Nat consent string v2 update (#40) * US Nat consent string v2 update * adds length check for strings * moving string lengths to consts * fix nj comment * adds test case for too long and too short for all v1 strings. updates usnat with v1 label --- gpp_parsed_consent_fixture_test.go | 16 +-- mspa_parsed_consent_fixture_test.go | 84 ++++++++++---- mspa_parsed_consent_test.go | 12 +- mspa_sections.go | 172 ++++++++++++++++++++++++---- 4 files changed, 234 insertions(+), 50 deletions(-) diff --git a/gpp_parsed_consent_fixture_test.go b/gpp_parsed_consent_fixture_test.go index cb3aea1..788954b 100644 --- a/gpp_parsed_consent_fixture_test.go +++ b/gpp_parsed_consent_fixture_test.go @@ -6,12 +6,14 @@ import ( // Test fixtures can be created here: https://iabgpp.com/ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ - // Valid GPP w/ US National MSPA, No Subsection (is the same as false GPC subsection). + // Valid GPP w/ V1 US National MSPA, No Subsection (is the same as false GPC subsection). "DBABLA~BVVqAAEABCA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]}, - // Valid GPP w/ US National MSPA, Subsection of GPC False. + // Valid GPP w/ V1 US National MSPA, Subsection of GPC False. "DBABLA~BVVqAAEABCA.QA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]}, - // Valid GPP w/ US National MSPA, Subsection of GPC True. + // Valid GPP w/ V1 US National MSPA, Subsection of GPC True. "DBABLA~BVVqAAEABCA.YA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.YA"]}, + // Valid GPP w/ V2 US National MSPA, Subsection of GPC True. + "DBABLA~CVVVVVVVVVVW.YA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["CVVVVVVVVVVW.YA"]}, // Valid GPP w/ US California MSPA, Subsection of GPC False. "DBABBg~BVoYYZoI": {iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"]}, // Valid GPP w/ US Virginia MSPA, Subsection of GPC False. @@ -22,12 +24,12 @@ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ "DBABFg~BVaGGGCA": {iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"]}, // Valid GPP w/ US Connecticut MSPA, Subsection of GPC False. "DBABVg~BVoYYYQg": {iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"]}, - // Valid GPP w/ US US National and Virgina MSPA, Subsection of GPC False. + // Valid GPP w/ US National and Virginia MSPA, Subsection of GPC False. "DBACLMA~BVVqAAEABCA~BVoYYYI": { iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"], iabconsent.UsVirginiaSID: mspaConsentFixtures[iabconsent.UsVirginiaSID]["BVoYYYI"], }, - // Valid GPP w/ US US National, California MSPA, Virgina MSPA, Colorado MSPA, and Utah Subsection of GPC False. + // Valid GPP w/ V1 US National, California MSPA, Virgina MSPA, Colorado MSPA, and Utah Subsection of GPC False. "DBABrGA~BVVqAAEABCA~BVoYYZoI~BVoYYYI~BVoYYQg~BVaGGGCA~BVoYYYQg": { iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"], iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"], @@ -36,7 +38,7 @@ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"], iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"], }, - // Valid GPP w/ US US National, California MSPA, Virgina MSPA, Colorado MSPA, Utah MSPA, Conneticut MSPA, Florida MSPA and Montana MSPA Subsection of GPC False. + // Valid GPP w/ V1 US National, California MSPA, Virginia MSPA, Colorado MSPA, Utah MSPA, Conneticut MSPA, Florida MSPA and Montana MSPA Subsection of GPC False. "DBABrWA~BVVqAAEABCA~BVoYYZoI~BVoYYYI~BVoYYQg~BVaGGGCA~BVoYYYQg~Bqqqqqqo~Bqqqqqqo": { iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"], iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"], @@ -50,7 +52,7 @@ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{ // Valid GPP string w/ sections for EU TCF V2 and US Privacy // Since both are not supported, Consent fixture should be blank. "DBACNY~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN": {}, - // Valid GPP w/ US National MSPA and US Privacy, but skip US Privacy until supported. + // Valid GPP w/ V1 US National MSPA and US Privacy, but skip US Privacy until supported. "DBABzw~1YNN~BVVqAAEABCA.QA": {7: mspaConsentFixtures[7]["BVVqAAEABCA.QA"]}, // Valid GPP w/ US Florida MSPA, Subsection of GPC False. "DBABAw~Bqqqqqqo": {iabconsent.UsFloridaSID: mspaConsentFixtures[iabconsent.UsFloridaSID]["Bqqqqqqo"]}, diff --git a/mspa_parsed_consent_fixture_test.go b/mspa_parsed_consent_fixture_test.go index f0f1cc4..3a7f196 100644 --- a/mspa_parsed_consent_fixture_test.go +++ b/mspa_parsed_consent_fixture_test.go @@ -11,7 +11,7 @@ import ( var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ // UsNational iabconsent.UsNationalSID: { - // usnat without false GPC subsection. + // usnat v1 without false GPC subsection. "BVVqAAEABCA.QA": { Version: 1, SharingNotice: iabconsent.NoticeProvided, @@ -46,7 +46,7 @@ var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ MspaOptOutOptionMode: iabconsent.MspaNotApplicable, MspaServiceProviderMode: iabconsent.MspaNo, }, - // usnat with true GPC subsection. + // usnat v1 with true GPC subsection. "BVVqAAEABCA.YA": { Version: 1, SharingNotice: iabconsent.NoticeProvided, @@ -82,7 +82,7 @@ var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ MspaServiceProviderMode: iabconsent.MspaNo, Gpc: true, }, - // usnat without subsection. + // usnat v1 without subsection. "BqqAqqqqqqA": { Version: 1, SharingNotice: iabconsent.NoticeNotProvided, @@ -118,7 +118,49 @@ var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ MspaServiceProviderMode: iabconsent.MspaNo, Gpc: false, }, + // usnat v2 with true GPC subsection. + "CVVVVVVVVVVW.YA": { + Version: 2, + SharingNotice: iabconsent.NoticeProvided, + SaleOptOutNotice: iabconsent.NoticeProvided, + SharingOptOutNotice: iabconsent.NoticeProvided, + TargetedAdvertisingOptOutNotice: iabconsent.NoticeProvided, + SensitiveDataProcessingOptOutNotice: iabconsent.NoticeProvided, + SensitiveDataLimitUseNotice: iabconsent.NoticeProvided, + SaleOptOut: iabconsent.OptedOut, + SharingOptOut: iabconsent.OptedOut, + TargetedAdvertisingOptOut: iabconsent.OptedOut, + SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.NoConsent, + 1: iabconsent.NoConsent, + 2: iabconsent.NoConsent, + 3: iabconsent.NoConsent, + 4: iabconsent.NoConsent, + 5: iabconsent.NoConsent, + 6: iabconsent.NoConsent, + 7: iabconsent.NoConsent, + 8: iabconsent.NoConsent, + 9: iabconsent.NoConsent, + 10: iabconsent.NoConsent, + 11: iabconsent.NoConsent, + 12: iabconsent.NoConsent, + 13: iabconsent.NoConsent, + 14: iabconsent.NoConsent, + 15: iabconsent.NoConsent, + }, + KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + 0: iabconsent.NoConsent, + 1: iabconsent.NoConsent, + 2: iabconsent.NoConsent, + }, + PersonalDataConsents: iabconsent.NoConsent, + MspaCoveredTransaction: iabconsent.MspaYes, + MspaOptOutOptionMode: iabconsent.MspaYes, + MspaServiceProviderMode: iabconsent.MspaYes, + Gpc: true, + }, }, + // California iabconsent.UsCaliforniaSID: { // usca with subsection of GPC True. @@ -728,15 +770,15 @@ var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ SensitiveDataProcessingOptOutNotice: iabconsent.NoticeProvided, SaleOptOut: iabconsent.OptedOut, TargetedAdvertisingOptOut: iabconsent.OptedOut, - SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ - 0: iabconsent.NoConsent, - 1: iabconsent.NoConsent, - 2: iabconsent.NoConsent, - 3: iabconsent.NoConsent, - 4: iabconsent.NoConsent, - 5: iabconsent.NoConsent, - 6: iabconsent.NoConsent, - 7: iabconsent.NoConsent, + SensitiveDataProcessingOptOuts: map[int]iabconsent.MspaOptout{ + 0: iabconsent.OptedOut, + 1: iabconsent.OptedOut, + 2: iabconsent.OptedOut, + 3: iabconsent.OptedOut, + 4: iabconsent.OptedOut, + 5: iabconsent.OptedOut, + 6: iabconsent.OptedOut, + 7: iabconsent.OptedOut, }, KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ 0: iabconsent.NoConsent, @@ -755,15 +797,15 @@ var mspaConsentFixtures = map[int]map[string]*iabconsent.MspaParsedConsent{ SensitiveDataProcessingOptOutNotice: iabconsent.NoticeProvided, SaleOptOut: iabconsent.OptedOut, TargetedAdvertisingOptOut: iabconsent.OptedOut, - SensitiveDataProcessingConsents: map[int]iabconsent.MspaConsent{ - 0: iabconsent.NoConsent, - 1: iabconsent.NoConsent, - 2: iabconsent.NoConsent, - 3: iabconsent.NoConsent, - 4: iabconsent.NoConsent, - 5: iabconsent.NoConsent, - 6: iabconsent.NoConsent, - 7: iabconsent.NoConsent, + SensitiveDataProcessingOptOuts: map[int]iabconsent.MspaOptout{ + 0: iabconsent.OptedOut, + 1: iabconsent.OptedOut, + 2: iabconsent.OptedOut, + 3: iabconsent.OptedOut, + 4: iabconsent.OptedOut, + 5: iabconsent.OptedOut, + 6: iabconsent.OptedOut, + 7: iabconsent.OptedOut, }, KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ 0: iabconsent.NoConsent, diff --git a/mspa_parsed_consent_test.go b/mspa_parsed_consent_test.go index e790cf8..bb0529a 100644 --- a/mspa_parsed_consent_test.go +++ b/mspa_parsed_consent_test.go @@ -216,13 +216,23 @@ func (s *MspaSuite) TestParseMSPAError(c *check.C) { { desc: "Wrong Version.", consentString: "DVVqAAEABA", - expected: "non-v1 string passed.", + expected: "unsupported version: 3", }, { desc: "Bad Decoding.", consentString: "$%&*(", expected: "parse %s consent string: illegal base64 data at input byte 0", }, + { + desc: "Invalid Section Length. Too long for all v1 strings", + consentString: "BqqAqqqqqqqqAA", + expected: "invalid consent string length for v1", + }, + { + desc: "Invalid Section Length. Too short for all v1 strings", + consentString: "BqqA", + expected: "invalid consent string length for v1", + }, } for _, s := range mspaTests { for _, t := range tcs { diff --git a/mspa_sections.go b/mspa_sections.go index 08f7cdf..2ea5f8e 100644 --- a/mspa_sections.go +++ b/mspa_sections.go @@ -2,11 +2,49 @@ package iabconsent import ( "encoding/base64" + "fmt" "strings" "github.com/pkg/errors" ) +const ( + // MspaUsNationalV1StringLength is 60 bits padded with 4 bits of 0s making valid length 64 bits + MspaUsNationalV1StringLength = 64 + // MspaUsNationalV2StringLength is 70 bits padded with 2 bits of 0s making valid length 72 bits + MspaUsNationalV2StringLength = 72 + // MspaUsCaV1StringLength is 46 bits padded with 2 bits of 0s making valid length 48 bits + MspaUsCaV1StringLength = 48 + // MspaUsVaV1StringLength is 40 bits no padding needed + MspaUsVaV1StringLength = 40 + // MspaUsCoV1StringLength is 38 bits padded with 2 bits of 0s making valid length 40 bits + MspaUsCoV1StringLength = 40 + // MspaUsUtV1StringLength is 42 bits padded with 6 bits of 0s making valid length 48 bits + MspaUsUtV1StringLength = 48 + // MspaUsCtV1StringLength is 44 bits padded with 4 bits of 0s making valid length 48 bits + MspaUsCtV1StringLength = 48 + // MspaUsFlV1StringLength is 46 bits padded with 2 bits of 0s making valid length 48 bits + MspaUsFlV1StringLength = 48 + // MspaUsMtV1StringLength is 46 bits padded with 2 bits of 0s making valid length 48 bits + MspaUsMtV1StringLength = 48 + // MspaUsOrV1StringLength is 52 bits padded with 4 bits of 0s making valid length 56 bits + MspaUsOrV1StringLength = 56 + // MspaUsTxV1StringLength is 42 bits padded with 6 bits of 0s making valid length 48 bits + MspaUsTxV1StringLength = 48 + // MspaUsDeV1StringLength is 52 bits padded with 4 bits of 0s making valid length 56 bits + MspaUsDeV1StringLength = 56 + // MspaUsIaV1StringLength is 42 bits padded with 6 bits of 0s making valid length 48 bits + MspaUsIaV1StringLength = 48 + // MspaUsNeV1StringLength is 42 bits padded with 6 bits of 0s making valid length 48 bits + MspaUsNeV1StringLength = 48 + // MspaUsNhV1StringLength is 46 bits padded with 2 bits of 0s making valid length 48 bits + MspaUsNhV1StringLength = 48 + // MspaUsNjV1StringLength is 54 bits padded with 2 bits of 0s making valid length 56 bits + MspaUsNjV1StringLength = 56 + // MspaUsTnV1StringLength is 40 bits with no padding making valid length 40 bits + MspaUsTnV1StringLength = 40 +) + type MspaUsNational struct { GppSection } @@ -125,12 +163,21 @@ func (m *MspaUsNational) ParseConsent() (GppParsedConsent, error) { // This block of code directly describes the format of the payload. // The spec for the consent string can be found here: - // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections/US-National#core-segment + // https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20Multi-State%20Privacy%20Agreement%20(MSPA)%20US%20National%20Technical%20Specification.md var p = &MspaParsedConsent{} p.Version, _ = r.ReadInt(6) - if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + // Support both v1 and v2 + if p.Version != 1 && p.Version != 2 { + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 and v2 + + if p.Version == 1 && r.Size() != MspaUsNationalV1StringLength { + return nil, errors.New("invalid consent string length for v1") + } else if p.Version == 2 && r.Size() != MspaUsNationalV2StringLength { + return nil, errors.New("invalid consent string length for v2") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -142,8 +189,15 @@ func (m *MspaUsNational) ParseConsent() (GppParsedConsent, error) { p.SaleOptOut, _ = r.ReadMspaOptOut() p.SharingOptOut, _ = r.ReadMspaOptOut() p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() - p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(12) - p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(2) + + // see spec in IAB GPP repo for differences between v1 and v2 + if p.Version == 1 { + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(12) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(2) + } else if p.Version == 2 { + p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(16) + p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(3) + } p.PersonalDataConsents, _ = r.ReadMspaConsent() p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() // 0 is not a valid value according to the docs for MspaCoveredTransaction. Instead of erroring, @@ -180,7 +234,12 @@ func (m *MspaUsCA) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsCaV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SaleOptOutNotice, _ = r.ReadMspaNotice() @@ -227,7 +286,12 @@ func (m *MspaUsVA) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsVaV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -272,7 +336,12 @@ func (m *MspaUsCO) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsCoV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -317,7 +386,12 @@ func (m *MspaUsUT) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsUtV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -363,7 +437,12 @@ func (m *MspaUsCT) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsCtV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -408,7 +487,12 @@ func (m *MspaUsFL) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsFlV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -454,7 +538,12 @@ func (m *MspaUsMT) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsMtV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -500,7 +589,12 @@ func (m *MspaUsOR) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsOrV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -546,7 +640,12 @@ func (m *MspaUsTX) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsTxV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -592,7 +691,12 @@ func (m *MspaUsDE) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsDeV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -621,6 +725,7 @@ func (m *MspaUsDE) ParseConsent() (GppParsedConsent, error) { return p, r.Err } +// Fix Iowa implementation func (m *MspaUsIA) ParseConsent() (GppParsedConsent, error) { var segments = strings.Split(m.sectionValue, ".") @@ -638,7 +743,12 @@ func (m *MspaUsIA) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsIaV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -647,7 +757,7 @@ func (m *MspaUsIA) ParseConsent() (GppParsedConsent, error) { p.SensitiveDataProcessingOptOutNotice, _ = r.ReadMspaNotice() p.SaleOptOut, _ = r.ReadMspaOptOut() p.TargetedAdvertisingOptOut, _ = r.ReadMspaOptOut() - p.SensitiveDataProcessingConsents, _ = r.ReadMspaBitfieldConsent(8) + p.SensitiveDataProcessingOptOuts, _ = r.ReadMspaBitfieldOptOut(8) p.KnownChildSensitiveDataConsents, _ = r.ReadMspaBitfieldConsent(1) p.MspaCoveredTransaction, _ = r.ReadMspaNaYesNo() p.MspaOptOutOptionMode, _ = r.ReadMspaNaYesNo() @@ -682,7 +792,12 @@ func (m *MspaUsNE) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsNeV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -726,7 +841,12 @@ func (m *MspaUsNH) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsNhV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -770,7 +890,12 @@ func (m *MspaUsNJ) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsNjV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() @@ -814,7 +939,12 @@ func (m *MspaUsTN) ParseConsent() (GppParsedConsent, error) { p.Version, _ = r.ReadInt(6) if p.Version != 1 { - return nil, errors.New("non-v1 string passed.") + return nil, errors.New("unsupported version: " + fmt.Sprint(p.Version)) + } + + // validate the length of the bit string for v1 + if p.Version == 1 && r.Size() != MspaUsTnV1StringLength { + return nil, errors.New("invalid consent string length for v1") } p.SharingNotice, _ = r.ReadMspaNotice() From 8fb3fbec3e5af760004a4a11adf4039858afdccb Mon Sep 17 00:00:00 2001 From: Atlantis Bot Date: Fri, 6 Jun 2025 16:29:06 -0400 Subject: [PATCH 09/10] Manage Backstage metadata by Terraform --- catalog-info.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/catalog-info.yaml b/catalog-info.yaml index 547230b..88369e9 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -8,4 +8,5 @@ "description": "A Go implementation of the IAB Consent String Specs (v1.1 and v2)" "name": "iabconsent" "tags": [] +"spec": {} # END TERRAFORM MANAGED BLOCK From ffde1a55f732acd301343fe720b9fb74924330b2 Mon Sep 17 00:00:00 2001 From: Atlantis Bot Date: Tue, 5 Aug 2025 16:45:16 -0400 Subject: [PATCH 10/10] Manage Backstage metadata by Terraform https://github.com/LiveRamp/infrastructure/pull/44929