@@ -2,12 +2,14 @@ package system
22
33import (
44 "fmt"
5+ "strings"
56 "time"
67
78 "github.com/flanksource/config-db/api"
89 v1 "github.com/flanksource/config-db/api/v1"
910 "github.com/flanksource/duty/models"
1011 "github.com/flanksource/duty/query"
12+ "github.com/flanksource/duty/rbac"
1113 "github.com/flanksource/duty/rbac/policy"
1214 "github.com/google/uuid"
1315 "github.com/lib/pq"
@@ -171,6 +173,13 @@ func scrapeAccessEntities(ctx api.ScrapeContext, scraperID uuid.UUID) v1.ScrapeR
171173
172174 result .ExternalRoles = scrapePlaybookRoles (scraperID )
173175
176+ access , errAccess := scrapePlaybookAccess (ctx , scraperID , users )
177+ if errAccess != nil {
178+ result = result .SetError (errAccess )
179+ return result
180+ }
181+ result .ConfigAccess = access
182+
174183 return result
175184}
176185
@@ -221,22 +230,85 @@ func scrapeTeams(ctx api.ScrapeContext, scraperID uuid.UUID) ([]models.ExternalG
221230}
222231
223232func scrapePlaybookRoles (scraperID uuid.UUID ) []models.ExternalRole {
224- return []models. ExternalRole {
225- {
226- Name : policy .ActionPlaybookRun ,
227- Tenant : "mission-control" ,
228- RoleType : "playbook-action" ,
229- Aliases : pq. StringArray { "role:" + policy . ActionPlaybookRun },
230- ScraperID : & scraperID ,
231- CreatedAt : time . Now (),
232- },
233- {
234- Name : policy . ActionPlaybookApprove ,
233+ actions := [] string {
234+ policy . ActionMCPRun ,
235+ policy .ActionPlaybookRun ,
236+ policy . ActionPlaybookApprove ,
237+ policy . ActionPlaybookCancel ,
238+ }
239+
240+ roles := make ([]models. ExternalRole , 0 , len ( actions ))
241+ for _ , action := range actions {
242+ roles = append ( roles , models. ExternalRole {
243+ Name : action ,
235244 Tenant : "mission-control" ,
236245 RoleType : "playbook-action" ,
237- Aliases : pq.StringArray {"role:" + policy . ActionPlaybookApprove },
246+ Aliases : pq.StringArray {"role:" + action },
238247 ScraperID : & scraperID ,
239248 CreatedAt : time .Now (),
240- },
249+ })
250+ }
251+
252+ return roles
253+ }
254+
255+ func scrapePlaybookAccess (ctx api.ScrapeContext , scraperID uuid.UUID , users []models.ExternalUser ) ([]v1.ExternalConfigAccess , error ) {
256+ actions := []string {
257+ policy .ActionMCPRun ,
258+ policy .ActionPlaybookRun ,
259+ policy .ActionPlaybookApprove ,
260+ policy .ActionPlaybookCancel ,
261+ }
262+ source := "mission-control-rbac"
263+ access := make ([]v1.ExternalConfigAccess , 0 )
264+
265+ for _ , user := range users {
266+ personID := personIDFromAliases (user .Aliases )
267+ if personID == "" {
268+ continue
269+ }
270+
271+ for _ , action := range actions {
272+ response , err := rbac .RunSubjectAccessSearch (ctx .DutyContext (), rbac.SubjectAccessSearchRequest {
273+ Subject : personID ,
274+ Action : action ,
275+ ResourceTypes : []string {"playbook" },
276+ })
277+ if err != nil {
278+ return nil , fmt .Errorf ("error running playbook access search for user %s action %s: %w" , personID , action , err )
279+ }
280+
281+ for _ , result := range response .Results {
282+ if result .ResourceType != "playbook" {
283+ continue
284+ }
285+
286+ playbookID , err := uuid .Parse (result .ID )
287+ if err != nil {
288+ return nil , fmt .Errorf ("invalid playbook id from access search %q: %w" , result .ID , err )
289+ }
290+
291+ access = append (access , v1.ExternalConfigAccess {
292+ ConfigID : playbookID ,
293+ ExternalUserAliases : []string {"people:" + personID },
294+ ExternalRoleAliases : []string {"role:" + action },
295+ ScraperID : & scraperID ,
296+ Source : & source ,
297+ CreatedAt : time .Now (),
298+ ConfigExternalID : v1.ExternalID {ConfigID : playbookID .String (), ConfigType : "MissionControl::Playbook" },
299+ })
300+ }
301+ }
302+ }
303+
304+ return access , nil
305+ }
306+
307+ func personIDFromAliases (aliases pq.StringArray ) string {
308+ for _ , alias := range aliases {
309+ if strings .HasPrefix (alias , "people:" ) {
310+ return strings .TrimPrefix (alias , "people:" )
311+ }
241312 }
313+ return ""
242314}
0 commit comments