@@ -21,11 +21,12 @@ import (
2121
2222// PermissionManifest is the JSON output for a provider's permissions.
2323type PermissionManifest struct {
24- Provider string `json:"provider"`
25- Version string `json:"version"`
26- GeneratedAt string `json:"generated_at"`
27- Permissions []string `json:"permissions"`
28- Details []PermissionDetail `json:"details"`
24+ Provider string `json:"provider"`
25+ Version string `json:"version"`
26+ GeneratedAt string `json:"generated_at"`
27+ Permissions []string `json:"permissions"`
28+ Details []PermissionDetail `json:"details"`
29+ OrgLevelPermissions []string `json:"org_level_permissions,omitempty"`
2930}
3031
3132// PermissionDetail describes a single extracted API call and its mapped permission.
@@ -34,6 +35,7 @@ type PermissionDetail struct {
3435 Service string `json:"service"`
3536 Action string `json:"action"`
3637 SourceFile string `json:"source_file"`
38+ Scope string `json:"scope,omitempty"`
3739}
3840
3941func main () {
@@ -71,16 +73,35 @@ func main() {
7173 os .Exit (0 )
7274 }
7375
74- // Deduplicate and sort permissions
76+ // Mark org-level permissions (GCP only)
77+ if providerName == "gcp" {
78+ for i := range details {
79+ if gcpOrgLevelPermissions [details [i ].Permission ] {
80+ details [i ].Scope = "org"
81+ }
82+ }
83+ }
84+
85+ // Deduplicate and sort permissions, separating org-level ones
7586 permSet := map [string ]bool {}
87+ orgPermSet := map [string ]bool {}
7688 for _ , d := range details {
77- permSet [d .Permission ] = true
89+ if d .Scope == "org" {
90+ orgPermSet [d .Permission ] = true
91+ } else {
92+ permSet [d .Permission ] = true
93+ }
7894 }
7995 permissions := make ([]string , 0 , len (permSet ))
8096 for p := range permSet {
8197 permissions = append (permissions , p )
8298 }
8399 sort .Strings (permissions )
100+ orgPermissions := make ([]string , 0 , len (orgPermSet ))
101+ for p := range orgPermSet {
102+ orgPermissions = append (orgPermissions , p )
103+ }
104+ sort .Strings (orgPermissions )
84105
85106 // Sort details for stable output
86107 sort .Slice (details , func (i , j int ) bool {
@@ -103,11 +124,12 @@ func main() {
103124 }
104125
105126 manifest := PermissionManifest {
106- Provider : providerName ,
107- Version : version ,
108- GeneratedAt : deterministicTimestamp (),
109- Permissions : permissions ,
110- Details : details ,
127+ Provider : providerName ,
128+ Version : version ,
129+ GeneratedAt : deterministicTimestamp (),
130+ Permissions : permissions ,
131+ Details : details ,
132+ OrgLevelPermissions : orgPermissions ,
111133 }
112134
113135 if outputPath == "" {
@@ -919,6 +941,10 @@ var gcpPermissionOverrides = map[string]map[string]string{
919941 "backupdr" : {
920942 "ListDataSources" : "backupdr.bvdataSources.list" ,
921943 },
944+ "compute" : {
945+ "NetworkFirewallPolicies.Get" : "compute.firewallPolicies.get" ,
946+ "NetworkFirewallPolicies.List" : "compute.firewallPolicies.list" ,
947+ },
922948 "recommender" : {
923949 // recommender.recommendations.list is not a real permission; the Recommender
924950 // API uses type-specific permissions (e.g., recommender.iamPolicyRecommendations.list).
@@ -927,6 +953,19 @@ var gcpPermissionOverrides = map[string]map[string]string{
927953 },
928954}
929955
956+ // gcpOrgLevelPermissions are permissions that only apply at the organization
957+ // level, not the project level. They are placed in the org_level_permissions
958+ // section of the manifest instead of the main permissions list.
959+ var gcpOrgLevelPermissions = map [string ]bool {
960+ "resourcemanager.folders.get" : true ,
961+ "resourcemanager.folders.list" : true ,
962+ "resourcemanager.folders.search" : true ,
963+ "resourcemanager.organizations.get" : true ,
964+ "resourcemanager.organizations.getIamPolicy" : true ,
965+ "resourcemanager.projects.list" : true ,
966+ "resourcemanager.projects.search" : true ,
967+ }
968+
930969// gcpSkipMethods lists method names that match isGCPAPIMethod patterns but are
931970// actually protobuf getter methods or internal helpers, not real API calls.
932971var gcpSkipMethods = map [string ]bool {
@@ -1009,6 +1048,14 @@ func gcpRESTToPermission(service, resource, method string) string {
10091048 if resource == "" {
10101049 return ""
10111050 }
1051+
1052+ // Check for explicit overrides using "Resource.Method" as the key
1053+ if overrides , ok := gcpPermissionOverrides [service ]; ok {
1054+ if perm , ok := overrides [resource + "." + method ]; ok {
1055+ return perm
1056+ }
1057+ }
1058+
10121059 verb := ""
10131060 switch method {
10141061 case "List" , "AggregatedList" , "Aggregated" , "Pages" , "Search" :
0 commit comments