Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIS 4.01: Ensure that instances are not configured to use the default… #244

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions policies/templates/gcp_compute_default_service_account_v1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

apiVersion: templates.gatekeeper.sh/v1alpha1
kind: ConstraintTemplate
metadata:
name: gcp-compute-default-service-account-v1
spec:
crd:
spec:
names:
kind: GCPComputeDefaultServiceAccountConstraintV1
plural: gcpcomputedefaultserviceaccountconstraintsv1
validation:
openAPIV3Schema:
properties: {}
targets:
validation.gcp.forsetisecurity.org:
rego: | #INLINE("validator/compute_default_service_account.rego")
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

package templates.gcp.GCPComputeDefaultServiceAccountConstraintV1

import data.validator.gcp.lib as lib

deny[{
"msg": message,
"details": metadata,
}] {
constraint := input.constraint
asset := input.asset

asset.asset_type == "compute.googleapis.com/Instance"
service_account := asset.resource.data.serviceAccount[_]
scope := service_account.scope[_]

scope == "https://www.googleapis.com/auth/cloud-platform"

message := sprintf("Instance %v has default service account with full access to all Cloud APIs.", [asset.name])
metadata := {"resource": asset.name}
}
#ENDINLINE
28 changes: 28 additions & 0 deletions samples/compute_default_service_account.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
apiVersion: constraints.gatekeeper.sh/v1alpha1
kind: GCPComputeDefaultServiceAccountConstraintV1
metadata:
name: compute_default_service_account
annotations:
description: Ensure that instances are not configured to use the default service account with full access to all Cloud APIs
# This constraint is not certified by CIS.
bundles.validator.forsetisecurity.org/cis-v1.1: 4.01
spec:
severity: high
match:
gcp:
target: ["organization/*"]
parameters: {}
36 changes: 36 additions & 0 deletions validator/compute_default_service_account.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

package templates.gcp.GCPComputeDefaultServiceAccountConstraintV1

import data.validator.gcp.lib as lib

deny[{
"msg": message,
"details": metadata,
}] {
constraint := input.constraint
asset := input.asset

asset.asset_type == "compute.googleapis.com/Instance"
service_account := asset.resource.data.serviceAccount[_]
scope := service_account.scope[_]

scope == "https://www.googleapis.com/auth/cloud-platform"

message := sprintf("Instance %v has default service account with full access to all Cloud APIs.", [asset.name])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this block only checks scope but not service account

Suggest to add re_match("[email protected]$", service_account.email) to check for default compute engine service account

If we use custom service account, scope will always be full scope, which is actually recommended: https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#best_practices

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the recommendation! @charliewolf what do you think about this strategy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joecheuk So in my test CAI data i was not seeing service accounts with names like that. @katze120 Do you have an example asset JSON you could share?

metadata := {"resource": asset.name}
}
34 changes: 34 additions & 0 deletions validator/compute_default_service_account_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

package templates.gcp.GCPComputeDefaultServiceAccountConstraintV1

import data.validator.gcp.lib as lib

all_violations[violation] {
resource := data.test.fixtures.compute_default_service_account.assets[_]
constraint := data.test.fixtures.compute_default_service_account.constraints

issues := deny with input.asset as resource
with input.constraint as constraint

violation := issues[_]
}

test_violations_basic {
violation_resources := {r | r = all_violations[_].details.resource}
violation_resources == {"//compute.googleapis.com/projects/test-project/zones/us-east1-c/instances/vm-default"}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
[
{
"name": "//compute.googleapis.com/projects/test-project/zones/us-east1-c/instances/vm-default",
"asset_type": "compute.googleapis.com/Instance",
"resource": {
"version": "v1",
"discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
"discovery_name": "Instance",
"parent": "//cloudresourcemanager.googleapis.com/projects/68478495408",
"data": {
"canIpForward": false,
"cpuPlatform": "Intel Haswell",
"creationTimestamp": "2018-01-18T12:16:22.261-08:00",
"deletionProtection": false,
"disk": [
{
"autoDelete": true,
"boot": true,
"deviceName": "persistent-disk-0",
"guestOsFeature": [
{
"type": "VIRTIO_SCSI_MULTIQUEUE"
}
],
"index": 0,
"interface": "SCSI",
"license": [
"https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-9-stretch"
],
"mode": "READ_WRITE",
"source": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-c/disks/vm-no-ip",
"type": "PERSISTENT"
}
],
"id": "8987947392482197114",
"labelFingerprint": "42WmSpB8rSM=",
"machineType": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-c/machineTypes/g1-small",
"name": "vm-no-ip",
"networkInterfaces": [
{
"fingerprint": "+QCnSman4bQ=",
"ipAddress": "10.1.0.2",
"name": "nic0",
"network": "https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default",
"subnetwork": "https://www.googleapis.com/compute/v1/projects/test-project/regions/us-east1/subnetworks/default-us-east1"
}
],
"scheduling": {
"automaticRestart": true,
"onHostMaintenance": "MIGRATE",
"preemptible": false
},
"selfLink": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-c/instances/vm-no-ip",
"serviceAccount": [
{
"email": "[email protected]",
"scope": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
],
"startRestricted": false,
"status": "RUNNING",
"tags": {
"fingerprint": "42WmSpB8rSM="
},
"zone": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-c"
}
}
},
{
"name": "//compute.googleapis.com/projects/test-project/zones/us-east1-b/instances/vm-nondefault",
"asset_type": "compute.googleapis.com/Instance",
"resource": {
"version": "v1",
"discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest",
"discovery_name": "Instance",
"parent": "//cloudresourcemanager.googleapis.com/projects/68478495408",
"data": {
"canIpForward": true,
"cpuPlatform": "Unknown CPU Platform",
"creationTimestamp": "2018-06-20T14:46:40.689-07:00",
"deletionProtection": false,
"description": "",
"disk": [
{
"autoDelete": true,
"boot": true,
"deviceName": "vm-shielded",
"guestOsFeature": [
{
"type": "VIRTIO_SCSI_MULTIQUEUE"
}
],
"index": 0,
"interface": "SCSI",
"license": [
"https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-9-stretch"
],
"mode": "READ_WRITE",
"source": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-b/disks/vm-shielded",
"type": "PERSISTENT"
}
],
"id": "108591614595134928",
"labelFingerprint": "42WmSpB8rSM=",
"machineType": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-b/machineTypes/n1-standard-1",
"name": "vm-shielded",
"networkInterfaces": [
{
"accessConfigs": [
{
"externalIp": "35.196.151.107",
"name": "external-nat",
"networkTier": "PREMIUM",
"type": "ONE_TO_ONE_NAT"
}
],
"fingerprint": "FKYLBaTiCF0=",
"ipAddress": "10.142.0.2",
"name": "nic0",
"network": "https://www.googleapis.com/compute/v1/projects/test-project/global/networks/default",
"subnetwork": "https://www.googleapis.com/compute/v1/projects/test-project/regions/us-east1/subnetworks/default"
}
],
"scheduling": {
"automaticRestart": true,
"onHostMaintenance": "MIGRATE",
"preemptible": false
},
"selfLink": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-b/instances/vm-nondefault",
"serviceAccount": [
{
"email": "[email protected]",
"scope": [
]
}
],
"startRestricted": false,
"status": "TERMINATED",
"tags": {
"fingerprint": "42WmSpB8rSM="
},
"zone": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-b"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
apiVersion: constraints.gatekeeper.sh/v1alpha1
kind: GCPComputeDefaultServiceAccountConstraintV1
metadata:
name: compute_default_service_account
spec:
severity: high
match:
gcp:
target: ["organization/*"]
parameters: {}