Skip to content

Commit

Permalink
✨ Add gcp binary authorization resource (#4138)
Browse files Browse the repository at this point in the history
```
cnquery> gcp.project.binaryAuthorization { policy { * } }
gcp.project.binaryAuthorization: {
  policy: {
    kubernetesServiceAccountAdmissionRules: {}
    name: "projects/manuel-development-3/policy"
    globalPolicyEvaluationMode: "GLOBAL_POLICY_EVALUATION_MODE_UNSPECIFIED"
    defaultAdmissionRule: gcp.project.binaryAuthorizationControl.admissionRule id = projects/manuel-development-3/policy/defaultAdmissionRule
    admissionWhitelistPatterns: [
      0: "asia.gcr.io/gke-multi-cloud-release/**"
      1: "asia.gcr.io/google-containers/addon-resizer:*"
      ...
```
  • Loading branch information
jaym authored May 30, 2024
1 parent 868550f commit 7f743dc
Show file tree
Hide file tree
Showing 8 changed files with 585 additions and 9 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ingresstls
iotedge
ipsetforwardedipconfig
ipsetreferencestatement
istio
jira
jsonbody
labelmatchstatement
Expand Down
1 change: 1 addition & 0 deletions providers/gcp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (
cloud.google.com/go v0.114.0 // indirect
cloud.google.com/go/auth v0.5.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/binaryauthorization v1.8.3
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/secretmanager v1.13.1 // indirect
cloud.google.com/go/storage v1.41.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions providers/gcp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKF
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
cloud.google.com/go/bigquery v1.61.0 h1:w2Goy9n6gh91LVi6B2Sc+HpBl8WbWhIyzdvVvrAuEIw=
cloud.google.com/go/bigquery v1.61.0/go.mod h1:PjZUje0IocbuTOdq4DBOJLNYB0WF3pAKBHzAYyxCwFo=
cloud.google.com/go/binaryauthorization v1.8.3 h1:RHnEM4HXbWShlGhPA0Jzj2YYETCHxmisNMU0OE2fXQM=
cloud.google.com/go/binaryauthorization v1.8.3/go.mod h1:Cul4SsGlbzEsWPOz2sH8m+g2Xergb6ikspUyQ7iOThE=
cloud.google.com/go/compute v1.27.0 h1:EGawh2RUnfHT5g8f/FX3Ds6KZuIBC77hZoDrBvEZw94=
cloud.google.com/go/compute v1.27.0/go.mod h1:LG5HwRmWFKM2C5XxHRiNzkLLXW48WwvyVC0mfWsYPOM=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
Expand Down
138 changes: 138 additions & 0 deletions providers/gcp/resources/binary_authorization.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package resources

import (
"context"
"fmt"

binaryauthorization "cloud.google.com/go/binaryauthorization/apiv1"
"cloud.google.com/go/binaryauthorization/apiv1/binaryauthorizationpb"
"go.mondoo.com/cnquery/v11/llx"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v11/providers/gcp/connection"
"go.mondoo.com/cnquery/v11/types"
"google.golang.org/api/option"
)

func (g *mqlGcpProject) binaryAuthorization() (*mqlGcpProjectBinaryAuthorizationControl, error) {
if g.Id.Error != nil {
return nil, g.Id.Error
}
projectId := g.Id.Data

serviceEnabled, err := g.isServiceEnabled(service_binaryauthorization)
if err != nil {
return nil, err
}
if !serviceEnabled {
g.BinaryAuthorization.State = plugin.StateIsSet | plugin.StateIsNull
return nil, nil
}

conn := g.MqlRuntime.Connection.(*connection.GcpConnection)
credentials, err := conn.Credentials(binaryauthorization.DefaultAuthScopes()...)
if err != nil {
return nil, err
}

ctx := context.Background()
c, err := binaryauthorization.NewSystemPolicyClient(ctx, option.WithCredentials(credentials), option.WithQuotaProject(projectId))
if err != nil {
return nil, err
}

defer c.Close()

name := fmt.Sprintf("projects/%s/policy", projectId)
resp, err := c.GetSystemPolicy(ctx, &binaryauthorizationpb.GetSystemPolicyRequest{
Name: name,
})
if err != nil {
return nil, err
}

var admissionWhitelistPatterns []interface{}
for _, pattern := range resp.GetAdmissionWhitelistPatterns() {
admissionWhitelistPatterns = append(admissionWhitelistPatterns, pattern.GetNamePattern())
}

clusterAdmissionRules, err := g.toMqlBinaryAuthzAdmissionRules(resp.GetClusterAdmissionRules(), name, "clusterAdmissionRules")
if err != nil {
return nil, err
}

kubernetesNamespaceAdmissionRules, err := g.toMqlBinaryAuthzAdmissionRules(resp.GetKubernetesNamespaceAdmissionRules(), name, "kubernetesNamespaceAdmissionRules")
if err != nil {
return nil, err
}

kubernetesServiceAccountAdmissionRules, err := g.toMqlBinaryAuthzAdmissionRules(resp.GetKubernetesServiceAccountAdmissionRules(), name, "kubernetesServiceAccountAdmissionRules")
if err != nil {
return nil, err
}

istioServiceIdentityAdmissionRules, err := g.toMqlBinaryAuthzAdmissionRules(resp.GetIstioServiceIdentityAdmissionRules(), name, "istioServiceIdentityAdmissionRules")
if err != nil {
return nil, err
}

defaultAdmissionRule, err := g.toMqlBinaryAuthzAdmissionRule(resp.GetDefaultAdmissionRule(), fmt.Sprintf("%s/defaultAdmissionRule", name))
if err != nil {
return nil, err
}

updateTime := resp.GetUpdateTime().AsTime()

policy, err := CreateResource(g.MqlRuntime, "gcp.project.binaryAuthorizationControl.policy", map[string]*llx.RawData{
"__id": llx.StringData(name),
"name": llx.StringData(name),
"admissionWhitelistPatterns": llx.ArrayData(admissionWhitelistPatterns, types.String),
"globalPolicyEvaluationMode": llx.StringData(resp.GetGlobalPolicyEvaluationMode().String()),
"clusterAdmissionRules": llx.MapData(clusterAdmissionRules, types.Resource("gcp.project.binaryAuthorizationControl.admissionRule")),
"kubernetesNamespaceAdmissionRules": llx.MapData(kubernetesNamespaceAdmissionRules, types.Resource("gcp.project.binaryAuthorizationControl.admissionRule")),
"kubernetesServiceAccountAdmissionRules": llx.MapData(kubernetesServiceAccountAdmissionRules, types.Resource("gcp.project.binaryAuthorizationControl.admissionRule")),
"istioServiceIdentityAdmissionRules": llx.MapData(istioServiceIdentityAdmissionRules, types.Resource("gcp.project.binaryAuthorizationControl.admissionRule")),
"defaultAdmissionRule": llx.ResourceData(defaultAdmissionRule, "gcp.project.binaryAuthorizationControl.admissionRule"),
"updated": llx.TimeData(updateTime),
})
if err != nil {
return nil, err
}

bauthz, err := CreateResource(g.MqlRuntime, "gcp.project.binaryAuthorizationControl", map[string]*llx.RawData{
"__id": llx.StringData(fmt.Sprintf("projects/%s/binaryAuthorizationControl", projectId)),
"policy": llx.ResourceData(policy, "gcp.project.binaryAuthorizationControl.policy"),
})
if err != nil {
return nil, err
}

return bauthz.(*mqlGcpProjectBinaryAuthorizationControl), nil
}

func (g *mqlGcpProject) toMqlBinaryAuthzAdmissionRules(rules map[string]*binaryauthorizationpb.AdmissionRule, policyName string, ruleSetName string) (map[string]interface{}, error) {
mqlRules := make(map[string]interface{})
for ruleName, rule := range rules {
mqlId := fmt.Sprintf("%s/%s/%s", policyName, ruleSetName, ruleName)
mqlRule, err := g.toMqlBinaryAuthzAdmissionRule(rule, mqlId)
if err != nil {
return nil, err
}
mqlRules[ruleName] = mqlRule
}
return mqlRules, nil
}

func (g *mqlGcpProject) toMqlBinaryAuthzAdmissionRule(rule *binaryauthorizationpb.AdmissionRule, mqlId string) (plugin.Resource, error) {
var requiresAttestationsBy []interface{}
for _, attestation := range rule.GetRequireAttestationsBy() {
requiresAttestationsBy = append(requiresAttestationsBy, attestation)
}
return CreateResource(g.MqlRuntime, "gcp.project.binaryAuthorizationControl.admissionRule", map[string]*llx.RawData{
"__id": llx.StringData(mqlId),
"evaluationMode": llx.StringData(rule.GetEvaluationMode().String()),
"requireAttestationsBy": llx.ArrayData(requiresAttestationsBy, types.String),
})
}
39 changes: 38 additions & 1 deletion providers/gcp/resources/gcp.lr
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ gcp.project @defaults("name") {
storage() gcp.project.storageService
// Monitoring resources
monitoring() gcp.project.monitoringService
// Binary Authorization resources
binaryAuthorization() gcp.project.binaryAuthorizationControl
}

// Google Cloud (GCP) service
Expand Down Expand Up @@ -2808,4 +2810,39 @@ private gcp.project.monitoringService.alertPolicy {
updatedBy string
// Configuration for notification channels notifications
alertStrategy dict
}
}

private gcp.project.binaryAuthorizationControl {
// The policy for container image binary authorization
policy gcp.project.binaryAuthorizationControl.policy
}

private gcp.project.binaryAuthorizationControl.policy {
// The resource name
name string
// Controls the evaluation of a Google-maintained global admission policy for common system-level images
globalPolicyEvaluationMode string
// Admission policy allowlisting
admissionWhitelistPatterns []string
// Per-cluster admission rules
clusterAdmissionRules map[string]gcp.project.binaryAuthorizationControl.admissionRule
// Per-kubernetes-namespace admission rules
kubernetesNamespaceAdmissionRules map[string]gcp.project.binaryAuthorizationControl.admissionRule
// Per-kubernetes-service-account admission rules
kubernetesServiceAccountAdmissionRules map[string]gcp.project.binaryAuthorizationControl.admissionRule
// Per-istio-service-identity admission rules
istioServiceIdentityAdmissionRules map[string]gcp.project.binaryAuthorizationControl.admissionRule
// Default admission rule for a cluster without a per-cluster, per-kubernetes-service-account, or per-istio-service-identity admission rule
defaultAdmissionRule gcp.project.binaryAuthorizationControl.admissionRule
// Time when the policy was last updated
updated time
}

private gcp.project.binaryAuthorizationControl.admissionRule {
// How this admission rule will be evaluated
evaluationMode string
// The action when a pod creation is denied by the admission rule
enforcementMode string
// The resource names of the attestors that must attest to a container image
requireAttestationsBy []string
}
Loading

0 comments on commit 7f743dc

Please sign in to comment.