This repository was archived by the owner on Jul 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathbarnacle.json
More file actions
executable file
·458 lines (454 loc) · 18.4 KB
/
barnacle.json
File metadata and controls
executable file
·458 lines (454 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
{
"script":{
"released":"2019-02-27",
"license":"Licensed under the Apache License, Version 2.0",
"copyright":"Copyright 2020 Google LLC",
"icon":"security",
"title":"CM360 User Audit",
"description":"Gives CM clients ability to see which profiles have access to which parts of an account. Loads CM user profile mappings using the API into BigQuery and connects to a DataStudio dashboard.",
"image":"https://google.github.io/starthinker/static/barnacle.png",
"sample":"https://datastudio.google.com/open/1gjxHm0jUlQUd0jMuxaOlmrl8gOX1kyKT",
"test":"https://github.com/google/starthinker/blob/master/tests/barnacle.json",
"from":["cm360"],
"to":["datastudio", "bigquery" ],
"pitches":[
"Meet contractual access reporting information.",
"Reduce unauthorized use of CM accounts and assets.",
"Audit user access within CM.",
"Prevent malicious user access / behavior."
],
"impacts":{
"spend optimization":0,
"spend growth":0,
"time savings":90,
"account health":100,
"csat improvement":90
},
"instructions":[
"Wait for **BigQuery->{field:recipe_project}->{field:recipe_slug}->CM_...** to be created.",
"Wait for **BigQuery->{field:recipe_project}->{field:recipe_slug}->Barnacle_...** to be created, then copy and connect the following data sources.",
"Join the [StarThinker Assets Group](https://groups.google.com/d/forum/starthinker-assets) to access the following assets",
"Copy [Barnacle Profile Advertiser Map](https://datastudio.google.com/open/1a6K-XdPUzCYRXZp1ZcmeOUOURc9wn2Jj) and connect.",
"Copy [Barnacle Profile Campaign Map](https://datastudio.google.com/open/1NEzrQWWnPjkD90iUwN-ASKbVBzoeBdoT) and connect.",
"Copy [Barnacle Profile Site Map](https://datastudio.google.com/open/1v_GRaitwPaHHKUzfJZYNBhzotvZ-bR7Y) and connect.",
"Copy [Barnacle Profiles Connections](https://datastudio.google.com/open/14tWlh7yiqzxKJIppMFVOw2MoMtQV_ucE) and connect.",
"Copy [Barnacle Report Delivery Profiles](https://datastudio.google.com/open/1mavjxvHSEPfJq5aW4FYgCXsBCE5rthZG) and connect.",
"Copy [Barnacle Roles Duplicates](https://datastudio.google.com/open/1Azk_Nul-auinf4NnDq8T9fDyiKkUWD7A) and connect.",
"Copy [Barnacle Roles Not Used](https://datastudio.google.com/open/1ogoofpKtqkLwcW9qC_Ju_JvJdIajsjNI) and connect.",
"Copy [Barnacle Site Contacts Profiles](https://datastudio.google.com/open/1xLgZPjOPDtmPyEqYMiMbWwMI8-WTslfj) and connect.",
"If reports checked, copy [Barnacle Profile Report Map](https://datastudio.google.com/open/1-YGDiQPDnk0gD78_QOY5XdTXRlTrLeEq) and connect.",
"Copy [Barnacle Report](https://datastudio.google.com/open/1gjxHm0jUlQUd0jMuxaOlmrl8gOX1kyKT).",
"When prompted choose the new data sources you just created.",
"Or give these intructions to the client."
],
"authors":["kenjora@google.com", "ceh@google.com"]
},
"setup":{
"day":["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
"hour":[1, 3, 8]
},
"tasks":[
{ "dataset":{
"description":"The dataset will hold multiple tables, make sure it exists.",
"hour":[1],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "order":4, "default":"", "description":"Name of Google BigQuery dataset to create." }}
}},
{ "barnacle":{
"description":"Will create tables with format CM_* to hold each endpoint via a call to the API list function. Exclude reports for its own task.",
"hour":[1],
"auth":{"field":{ "name":"auth_read", "kind":"authentication", "order":0, "default":"user", "description":"Credentials used for reading data." }},
"reports":{"field":{ "name":"reports", "kind":"boolean", "order":3, "default":false, "description":"Include report audit, consumes significant API and data." }},
"accounts":{
"single_cell":true,
"values":{"field":{ "name":"accounts", "kind":"integer_list", "order":2, "default":[], "description":"Comma separated CM account ids." }}
},
"out":{
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "order":4, "default":"", "description":"Google BigQuery dataset to create tables in." }}
}
}},
{"bigquery":{
"hour":[8],
"description":"Combine profile, account, subaccount, and roles into one view, used by other views in this workflow.",
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
P.profileId AS profileId,
P.accountId AS accountId,
P.subaccountId AS subaccountId,
P.name AS Profile_Name,
P.email AS Profile_Email,
REGEXP_EXTRACT(P.email, r'@(.+)') AS Profile_Domain,
P.userAccessType AS Profile_userAccessType,
P.active AS Profie_active,
P.traffickerType AS Profile_traffickerType,
P.comments AS Profile_comments,
P.userRoleId AS Profile_userRoleId,
R.role_name AS Role_role_name,
R.role_defaultUserRole AS Role_role_defaultUserRole,
R.permission_name AS Role_permission_name,
R.permission_availability AS Role_permission_availability,
A.name AS Account_name,
A.active AS Account_active,
A.description AS Account_description,
A.locale AS Account_locale,
S.name AS SubAccount_name
FROM `{dataset}.CM_Profiles` AS P
LEFT JOIN `{dataset}.CM_Roles` AS R
ON P.userRoleId=R.roleId
LEFT JOIN `{dataset}.CM_Accounts` AS A
ON P.accountId=A.accountId
LEFT JOIN `{dataset}.CM_SubAccounts` AS S
ON P.accountId=S.accountId
AND P.subaccountId=S.subaccountId
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Profile_Role_Account_SubAccount_Map"
}
}},
{"bigquery":{
"description":"Combine profiles and advertisers.",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
APRASM.*,
A.advertiserId AS advertiserId,
A.name AS Advertiser_name,
A.status AS Advertiser_status,
A.defaultEmail AS Advertiser_defaultEmail,
A.suspended AS Advertiser_suspended
FROM `{dataset}.CM_Profile_Advertisers` As PA
LEFT JOIN `{dataset}.Barnacle_Profile_Role_Account_SubAccount_Map` AS APRASM
ON PA.profileID=APRASM.profileID
LEFT JOIN `{dataset}.CM_Advertisers` AS A
ON PA.advertiserId=A.advertiserId
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Profile_Advertiser_Map"
}
}},
{"bigquery":{
"description":"Profile to campaign mapping.",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
APRASM.*,
C.campaignId AS campaignId,
C.name AS Campaign_name,
C.archived AS Campaign_archived,
IF(C.startDate <= CURRENT_DATE() AND C.endDate >= CURRENT_DATE(), True, False) AS Campaign_running,
ROUND(TIMESTAMP_DIFF(CURRENT_TIMESTAMP(), C.lastModifiedInfo_time, DAY) / 7) AS Campaign_Modified_Weeks_Ago
FROM `.{dataset}.CM_Profile_Campaigns` As PC
LEFT JOIN `{dataset}.Barnacle_Profile_Role_Account_SubAccount_Map` AS APRASM
ON PC.profileID=APRASM.profileID
LEFT JOIN `{dataset}.CM_Campaigns` AS C
ON PC.campaignId=C.campaignId
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Profile_Campaign_Map"
}
}},
{"bigquery":{
"description":"The logic query for Deal Finder, transforms report into view used by datastudio.",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
APRASM.*,
R.reportId AS reportId,
R.name AS Report_name,
R.type AS Report_type,
R.format AS Report_format,
R.schedule_active AS Report_schedule_active,
R.schedule_repeats AS Report_schedule_repeats,
ROUND(TIMESTAMP_DIFF(CURRENT_TIMESTAMP(), R.lastModifiedTime, DAY) / 7) AS Report_Modified_Weeks_Ago,
DATE_DIFF(R.schedule_expirationDate, CURRENT_DATE(), MONTH) AS Report_Schedule_Weeks_To_Go
FROM `{dataset}.CM_Reports` As R
LEFT JOIN `{dataset}.Barnacle_Profile_Role_Account_SubAccount_Map` AS APRASM
ON R.profileID=APRASM.profileID
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Profile_Report_Map"
}
}},
{"bigquery":{
"description":"The logic query for Deal Finder, transforms report into view used by datastudio.",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
APRASM.*,
S.siteId AS siteId,
S.name AS Site_Name,
S.keyName AS Site_keyName,
S.approved AS Site_approved
FROM `{dataset}.CM_Profile_Sites` As PS
LEFT JOIN `{dataset}.Barnacle_Profile_Role_Account_SubAccount_Map` AS APRASM
ON PS.profileID=APRASM.profileID
LEFT JOIN `{dataset}.CM_Sites` AS S
ON PS.siteId=S.siteId
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Profile_Site_Map"
}
}},
{"bigquery":{
"description":"The logic query for Deal Finder, transforms report into view used by datastudio.",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
APRASM.*
FROM `{dataset}.Barnacle_Profile_Role_Account_SubAccount_Map` AS APRASM
LEFT JOIN `{dataset}.CM_Profile_Advertisers` AS PA
ON APRASM.profileId=PA.profileId
LEFT JOIN `{dataset}.CM_Profile_Campaigns` AS PC
ON APRASM.profileId=PC.profileId
LEFT JOIN `{dataset}.CM_Profile_Sites` AS PS
ON APRASM.profileId=PS.profileId
WHERE
PA.advertiserId IS NULL
AND PC.campaignId IS NULL
AND PS.siteId IS NULL
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Profiles_Connections"
}
}},
{"bigquery":{
"description":"",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
RD.accountId AS accountId,
RD.subaccountId AS subaccountId,
RD.reportId AS reportId,
A.name AS Account_name,
A.active AS Account_active,
SA.name as SubAccount_name,
R.name as Report_name,
R.schedule_active AS Report_schedule_active,
RD.emailOwnerDeliveryType AS Delivery_emailOwnerDeliveryType,
RD.deliveryType AS Delivery_deliveryType,
RD.email AS Delivery_email,
RD.message AS Delivery_message,
IF(RD.email in (SELECT email from `{dataset}.CM_Profiles`), True, False) AS Profile_Match_Exists
FROM `{dataset}.CM_Report_Deliveries` AS RD
LEFT JOIN `{dataset}.CM_Accounts` AS A
ON RD.accountId=A.accountId
LEFT JOIN `{dataset}.CM_SubAccounts` AS SA
ON RD.subaccountId=SA.subaccountId
LEFT JOIN `{dataset}.CM_Reports` AS R
ON RD.reportId=R.reportId
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Report_Delivery_Profiles"
}
}},
{"bigquery":{
"description":"",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
R.accountId AS accountId,
R.subaccountId AS subaccountId,
R.roleId AS roleId,
A.name AS Account_name,
A.active AS Account_active,
SA.name AS SubAccount_name,
R.role_name as Role_role_name,
R.role_defaultUserRole AS Role_role_defaultUserRole,
R.permission_name AS Role_permission_name,
R.permission_availability AS Role_permission_availability
FROM `{dataset}.CM_Roles` AS R
LEFT JOIN `{dataset}.CM_Accounts` AS A on R.accountId=A.accountId
LEFT JOIN `{dataset}.CM_SubAccounts` AS SA on R.subaccountId=SA.subaccountId
WHERE roleId NOT IN (
SELECT roleId FROM `{dataset}.CM_Profile_Roles`
)
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Roles_Not_Used"
}
}},
{"bigquery":{
"description":"",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
SELECT
SC.accountId AS accountId,
SC.subaccountId AS subaccountId,
SC.siteId AS siteId,
SC.contactId AS contactId,
A.name AS Account_name,
A.active AS Account_active,
SA.name as SubAccount_name,
S.name as Site_name,
S.approved AS Site_approved,
SC.email AS Site_Contact_email,
CONCAT(SC.firstName, ' ', sc.lastname) AS Site_Contact_Name,
SC.phone AS Site_Contact_phone,
SC.contactType AS Site_Contact_contactType,
IF(sc.email in (SELECT email from `{dataset}.CM_Profiles`), True, False) AS Profile_Match_Exists
FROM `{dataset}.CM_Site_Contacts` AS SC
LEFT JOIN `{dataset}.CM_Accounts` AS A
ON SC.accountId=A.accountId
LEFT JOIN `{dataset}.CM_SubAccounts` AS SA
ON SC.accountId=SA.accountId
AND SC.subaccountId=SA.subaccountId
LEFT JOIN `{dataset}.CM_Sites` AS S
ON SC.siteId=S.siteId
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Site_Contacts_Profiles"
}
}},
{"bigquery":{
"description":"",
"hour":[8],
"auth":{"field":{ "name":"auth_write", "kind":"authentication", "order":1, "default":"service", "description":"Credentials used for writing data." }},
"from":{
"legacy":false,
"query":"
WITH
profile_counts AS (
SELECT userRoleId, COUNT(profileId) as profile_count
FROM `{dataset}.CM_Profiles`
GROUP BY 1
),
permission_fingerprints AS (
SELECT
accountId,
subaccountId,
roleId,
role_name,
role_defaultUserRole,
SUM(profile_count) AS profile_count,
FARM_FINGERPRINT(
ARRAY_TO_STRING(
ARRAY_AGG(
DISTINCT permission_name ORDER BY permission_name ASC
), ',', '-'
)
) AS permissions_fingerprint
FROM
`{dataset}.CM_Roles` AS R
LEFT JOIN profile_counts AS P
ON R.roleId = P.userRoleId
GROUP BY
accountId,
subaccountId,
roleId,
role_name,
role_defaultUserRole
)
SELECT
PFL.accountId AS accountId,
A.name AS Account_name,
A.active AS Account_active,
PFL.subaccountId AS subaccountId,
SA.name AS SubAccount_name,
PFL.roleId AS roleId,
PFL.role_name AS role_name,
PFL.role_defaultUserRole AS role_defaultUserRole,
COALESCE(PFL.profile_count, 0) AS profile_count,
PFR.roleId AS duplicate_roleId,
PFR.role_name AS duplicate_role_name,
PFR.role_defaultUserRole AS duplicate_role_defaultUserRole,
COALESCE(PFR.profile_count, 0) AS duplicate_profile_count
FROM permission_fingerprints AS PFL
LEFT JOIN `{dataset}.CM_Accounts` AS A on PFL.accountId=A.accountId
LEFT JOIN `{dataset}.CM_SubAccounts` AS SA on PFL.subaccountId=SA.subaccountId
LEFT JOIN permission_fingerprints AS PFR
ON PFL.permissions_fingerprint=PFR.permissions_fingerprint
AND PFL.accountId=PFR.accountId
AND COALESCE(PFL.subaccountId, 0)=COALESCE(PFR.subaccountId, 0)
WHERE PFL.roleId != PFR.roleId
;
",
"parameters":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }}
}
},
"to":{
"dataset":{"field":{ "name":"recipe_slug", "kind":"string", "description":"Place where tables will be written in BigQuery." }},
"view":"Barnacle_Roles_Duplicates"
}
}}
]
}