Skip to content

Commit f075a50

Browse files
tas50claude
andcommitted
⭐ Add Security Command Center and VPC Service Controls resources
Add two new GCP service areas to the provider: **Security Command Center (SCC):** - Sources, Findings, NotificationConfigs, MuteConfigs, BigQueryExports - Available at org level (gcp.organization.scc*) and project level (gcp.project.sccFindings) - Uses wildcard source listing (sources/-) for cross-source finding queries **VPC Service Controls (Access Context Manager):** - AccessPolicies, AccessLevels, ServicePerimeters - Available at org level (gcp.organization.accessPolicies) - AccessLevels and ServicePerimeters lazy-loaded as sub-resources of AccessPolicy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e3df3ff commit f075a50

File tree

9 files changed

+2111
-22
lines changed

9 files changed

+2111
-22
lines changed

providers/gcp/go.mod

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ go 1.25.7
66

77
require (
88
cloud.google.com/go/accessapproval v1.8.8
9+
cloud.google.com/go/accesscontextmanager v1.9.7
910
cloud.google.com/go/aiplatform v1.121.0
1011
cloud.google.com/go/alloydb v1.21.0
1112
cloud.google.com/go/artifactregistry v1.20.0
@@ -31,6 +32,7 @@ require (
3132
cloud.google.com/go/run v1.16.0
3233
cloud.google.com/go/scheduler v1.11.8
3334
cloud.google.com/go/security v1.19.2
35+
cloud.google.com/go/securitycenter v1.38.1
3436
cloud.google.com/go/serviceusage v1.9.7
3537
cloud.google.com/go/spanner v1.89.0
3638
github.com/aws/smithy-go v1.24.2
@@ -43,7 +45,7 @@ require (
4345
go.mondoo.com/mql/v13 v13.2.0
4446
go.mondoo.com/ranger-rpc v0.8.0
4547
golang.org/x/oauth2 v0.36.0
46-
google.golang.org/api v0.273.0
48+
google.golang.org/api v0.273.1
4749
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7
4850
google.golang.org/protobuf v1.36.11
4951
)
@@ -293,8 +295,8 @@ require (
293295
golang.org/x/time v0.15.0 // indirect
294296
golang.org/x/tools v0.43.0 // indirect
295297
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
296-
google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7 // indirect
297-
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 // indirect
298+
google.golang.org/genproto/googleapis/api v0.0.0-20260401001100-f93e5f3e9f0f // indirect
299+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f // indirect
298300
google.golang.org/grpc v1.79.3
299301
gopkg.in/warnings.v0 v0.1.2 // indirect
300302
gopkg.in/yaml.v3 v3.0.1 // indirect

providers/gcp/go.sum

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
3333
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
3434
cloud.google.com/go/accessapproval v1.8.8 h1:gq8OS+rQWgGRo91D2qztN+ion6AZ2T1CxBIu0ifCmVo=
3535
cloud.google.com/go/accessapproval v1.8.8/go.mod h1:RFwPY9JDKseP4gJrX1BlAVsP5O6kI8NdGlTmaeDefmk=
36+
cloud.google.com/go/accesscontextmanager v1.9.7 h1:aKIfg7Jyc73pe8bzx0zypNdS5gfFdSvFvB8YNA9k2kA=
37+
cloud.google.com/go/accesscontextmanager v1.9.7/go.mod h1:i6e0nd5CPcrh7+YwGq4bKvju5YB9sgoAip+mXU73aMM=
3638
cloud.google.com/go/aiplatform v1.121.0 h1:8y8sNfVAW1DVhFbSbI7d8rrqBGGJFk6EoV6atidlyQc=
3739
cloud.google.com/go/aiplatform v1.121.0/go.mod h1:juMdDWeNphHV40KhWdN+563zNCOKNmLJjk5D2TA43ls=
3840
cloud.google.com/go/alloydb v1.21.0 h1:f8udyaV5PmAKcsTOOsIlgJdLBf4DrO+ML5o/iJvdCLY=
@@ -110,6 +112,8 @@ cloud.google.com/go/secretmanager v1.16.0 h1:19QT7ZsLJ8FSP1k+4esQvuCD7npMJml6hYz
110112
cloud.google.com/go/secretmanager v1.16.0/go.mod h1://C/e4I8D26SDTz1f3TQcddhcmiC3rMEl0S1Cakvs3Q=
111113
cloud.google.com/go/security v1.19.2 h1:cF3FkCRRbRC1oXuaGZFl3qU2sdu2gP3iOAHKzL5y04Y=
112114
cloud.google.com/go/security v1.19.2/go.mod h1:KXmf64mnOsLVKe8mk/bZpU1Rsvxqc0Ej0A6tgCeN93w=
115+
cloud.google.com/go/securitycenter v1.38.1 h1:D9zpeguY4frQU35GBw8+M6Gw79CiuTF9iVs4sFm3FDY=
116+
cloud.google.com/go/securitycenter v1.38.1/go.mod h1:Ge2D/SlG2lP1FrQD7wXHy8qyeloRenvKXeB4e7zO6z0=
113117
cloud.google.com/go/serviceusage v1.9.7 h1:vrBBeI2ESmri4BLGPz1YH2o37loIQ3DDTloYiDOe2lY=
114118
cloud.google.com/go/serviceusage v1.9.7/go.mod h1:JpBpv+4Zbe7+RiC9ydc6xgBUOntIL9tA85d2xKgV83g=
115119
cloud.google.com/go/spanner v1.89.0 h1:r3h5Z5RA8JRPf3HCvA6ujNhREIMhPY+MrDL9mkY8jS0=
@@ -1351,8 +1355,8 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr
13511355
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
13521356
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
13531357
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
1354-
google.golang.org/api v0.273.0 h1:r/Bcv36Xa/te1ugaN1kdJ5LoA5Wj/cL+a4gj6FiPBjQ=
1355-
google.golang.org/api v0.273.0/go.mod h1:JbAt7mF+XVmWu6xNP8/+CTiGH30ofmCmk9nM8d8fHew=
1358+
google.golang.org/api v0.273.1 h1:L7G/TmpAMz0nKx/ciAVssVmWQiOF6+pOuXeKrWVsquY=
1359+
google.golang.org/api v0.273.1/go.mod h1:JbAt7mF+XVmWu6xNP8/+CTiGH30ofmCmk9nM8d8fHew=
13561360
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
13571361
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
13581362
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1425,10 +1429,10 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
14251429
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
14261430
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0=
14271431
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I=
1428-
google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7 h1:41r6JMbpzBMen0R/4TZeeAmGXSJC7DftGINUodzTkPI=
1429-
google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:EIQZ5bFCfRQDV4MhRle7+OgjNtZ6P1PiZBgAKuxXu/Y=
1430-
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 h1:ndE4FoJqsIceKP2oYSnUZqhTdYufCYYkqwtFzfrhI7w=
1431-
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
1432+
google.golang.org/genproto/googleapis/api v0.0.0-20260401001100-f93e5f3e9f0f h1:K3zPU40OFjwD5YKADLMLoiL0L7JJpBgEdLqGuCNPfp0=
1433+
google.golang.org/genproto/googleapis/api v0.0.0-20260401001100-f93e5f3e9f0f/go.mod h1:EIQZ5bFCfRQDV4MhRle7+OgjNtZ6P1PiZBgAKuxXu/Y=
1434+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f h1:Rka45QInERYknkHYfJEPBQaoobXl+YpxTMjAKgWUq2A=
1435+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
14321436
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
14331437
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
14341438
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Copyright Mondoo, Inc. 2024, 2026
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
package resources
5+
6+
import (
7+
"context"
8+
9+
accesscontextmanager "cloud.google.com/go/accesscontextmanager/apiv1"
10+
acmpb "cloud.google.com/go/accesscontextmanager/apiv1/accesscontextmanagerpb"
11+
"go.mondoo.com/mql/v13/llx"
12+
"go.mondoo.com/mql/v13/providers/gcp/connection"
13+
"google.golang.org/api/iterator"
14+
"google.golang.org/api/option"
15+
)
16+
17+
func (g *mqlGcpAccesscontextmanagerAccessPolicy) id() (string, error) {
18+
return g.Name.Data, g.Name.Error
19+
}
20+
21+
func (g *mqlGcpAccesscontextmanagerAccessLevel) id() (string, error) {
22+
return g.Name.Data, g.Name.Error
23+
}
24+
25+
func (g *mqlGcpAccesscontextmanagerServicePerimeter) id() (string, error) {
26+
return g.Name.Data, g.Name.Error
27+
}
28+
29+
func newACMClient(conn *connection.GcpConnection) (*accesscontextmanager.Client, error) {
30+
creds, err := conn.Credentials(accesscontextmanager.DefaultAuthScopes()...)
31+
if err != nil {
32+
return nil, err
33+
}
34+
return accesscontextmanager.NewClient(context.Background(), option.WithCredentials(creds))
35+
}
36+
37+
func (g *mqlGcpOrganization) accessPolicies() ([]any, error) {
38+
if g.Id.Error != nil {
39+
return nil, g.Id.Error
40+
}
41+
42+
conn := g.MqlRuntime.Connection.(*connection.GcpConnection)
43+
orgId, err := conn.OrganizationID()
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
client, err := newACMClient(conn)
49+
if err != nil {
50+
return nil, err
51+
}
52+
defer client.Close()
53+
54+
it := client.ListAccessPolicies(context.Background(), &acmpb.ListAccessPoliciesRequest{
55+
Parent: "organizations/" + orgId,
56+
})
57+
58+
var res []any
59+
for {
60+
policy, err := it.Next()
61+
if err == iterator.Done {
62+
break
63+
}
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
mqlPolicy, err := CreateResource(g.MqlRuntime, "gcp.accesscontextmanager.accessPolicy", map[string]*llx.RawData{
69+
"name": llx.StringData(policy.Name),
70+
"title": llx.StringData(policy.Title),
71+
"parent": llx.StringData(policy.Parent),
72+
"etag": llx.StringData(policy.Etag),
73+
})
74+
if err != nil {
75+
return nil, err
76+
}
77+
res = append(res, mqlPolicy)
78+
}
79+
80+
return res, nil
81+
}
82+
83+
func (g *mqlGcpAccesscontextmanagerAccessPolicy) accessLevels() ([]any, error) {
84+
if g.Name.Error != nil {
85+
return nil, g.Name.Error
86+
}
87+
policyName := g.Name.Data
88+
89+
conn := g.MqlRuntime.Connection.(*connection.GcpConnection)
90+
client, err := newACMClient(conn)
91+
if err != nil {
92+
return nil, err
93+
}
94+
defer client.Close()
95+
96+
it := client.ListAccessLevels(context.Background(), &acmpb.ListAccessLevelsRequest{
97+
Parent: policyName,
98+
})
99+
100+
var res []any
101+
for {
102+
level, err := it.Next()
103+
if err == iterator.Done {
104+
break
105+
}
106+
if err != nil {
107+
return nil, err
108+
}
109+
110+
basic, err := protoToDict(level.GetBasic())
111+
if err != nil {
112+
return nil, err
113+
}
114+
custom, err := protoToDict(level.GetCustom())
115+
if err != nil {
116+
return nil, err
117+
}
118+
119+
mqlLevel, err := CreateResource(g.MqlRuntime, "gcp.accesscontextmanager.accessLevel", map[string]*llx.RawData{
120+
"name": llx.StringData(level.Name),
121+
"title": llx.StringData(level.Title),
122+
"description": llx.StringData(level.Description),
123+
"basic": llx.DictData(basic),
124+
"custom": llx.DictData(custom),
125+
"createTime": llx.TimeDataPtr(timestampAsTimePtr(level.CreateTime)),
126+
"updateTime": llx.TimeDataPtr(timestampAsTimePtr(level.UpdateTime)),
127+
})
128+
if err != nil {
129+
return nil, err
130+
}
131+
res = append(res, mqlLevel)
132+
}
133+
134+
return res, nil
135+
}
136+
137+
func (g *mqlGcpAccesscontextmanagerAccessPolicy) servicePerimeters() ([]any, error) {
138+
if g.Name.Error != nil {
139+
return nil, g.Name.Error
140+
}
141+
policyName := g.Name.Data
142+
143+
conn := g.MqlRuntime.Connection.(*connection.GcpConnection)
144+
client, err := newACMClient(conn)
145+
if err != nil {
146+
return nil, err
147+
}
148+
defer client.Close()
149+
150+
it := client.ListServicePerimeters(context.Background(), &acmpb.ListServicePerimetersRequest{
151+
Parent: policyName,
152+
})
153+
154+
var res []any
155+
for {
156+
perimeter, err := it.Next()
157+
if err == iterator.Done {
158+
break
159+
}
160+
if err != nil {
161+
return nil, err
162+
}
163+
164+
status, err := protoToDict(perimeter.Status)
165+
if err != nil {
166+
return nil, err
167+
}
168+
spec, err := protoToDict(perimeter.Spec)
169+
if err != nil {
170+
return nil, err
171+
}
172+
173+
mqlPerimeter, err := CreateResource(g.MqlRuntime, "gcp.accesscontextmanager.servicePerimeter", map[string]*llx.RawData{
174+
"name": llx.StringData(perimeter.Name),
175+
"title": llx.StringData(perimeter.Title),
176+
"description": llx.StringData(perimeter.Description),
177+
"perimeterType": llx.StringData(perimeter.PerimeterType.String()),
178+
"status": llx.DictData(status),
179+
"spec": llx.DictData(spec),
180+
"useExplicitDryRunSpec": llx.BoolData(perimeter.UseExplicitDryRunSpec),
181+
"createTime": llx.TimeDataPtr(timestampAsTimePtr(perimeter.CreateTime)),
182+
"updateTime": llx.TimeDataPtr(timestampAsTimePtr(perimeter.UpdateTime)),
183+
})
184+
if err != nil {
185+
return nil, err
186+
}
187+
res = append(res, mqlPerimeter)
188+
}
189+
190+
return res, nil
191+
}

0 commit comments

Comments
 (0)