From f39aa58c2191126793daf032e90dce6ebbfeeb0e Mon Sep 17 00:00:00 2001 From: Charlie Wolf Date: Mon, 30 Dec 2019 01:25:18 -0800 Subject: [PATCH] GCP 4.01; Ensure that instances are not configured to use the default service account with full access to all Cloud APIs --- ...cp_compute_default_service_account_v1.yaml | 68 ++++++++ samples/compute_default_service_account.yaml | 28 ++++ .../compute_default_service_account.rego | 36 +++++ .../compute_default_service_account_test.rego | 34 ++++ .../assets/data.json | 148 ++++++++++++++++++ .../constraints/data.yaml | 24 +++ 6 files changed, 338 insertions(+) create mode 100644 policies/templates/gcp_compute_default_service_account_v1.yaml create mode 100644 samples/compute_default_service_account.yaml create mode 100644 validator/compute_default_service_account.rego create mode 100644 validator/compute_default_service_account_test.rego create mode 100644 validator/test/fixtures/compute_default_service_account/assets/data.json create mode 100644 validator/test/fixtures/compute_default_service_account/constraints/data.yaml diff --git a/policies/templates/gcp_compute_default_service_account_v1.yaml b/policies/templates/gcp_compute_default_service_account_v1.yaml new file mode 100644 index 000000000..04314cb09 --- /dev/null +++ b/policies/templates/gcp_compute_default_service_account_v1.yaml @@ -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 diff --git a/samples/compute_default_service_account.yaml b/samples/compute_default_service_account.yaml new file mode 100644 index 000000000..ba91467f1 --- /dev/null +++ b/samples/compute_default_service_account.yaml @@ -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: {} diff --git a/validator/compute_default_service_account.rego b/validator/compute_default_service_account.rego new file mode 100644 index 000000000..4b566e5c4 --- /dev/null +++ b/validator/compute_default_service_account.rego @@ -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]) + metadata := {"resource": asset.name} +} diff --git a/validator/compute_default_service_account_test.rego b/validator/compute_default_service_account_test.rego new file mode 100644 index 000000000..497ad7ef1 --- /dev/null +++ b/validator/compute_default_service_account_test.rego @@ -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"} +} diff --git a/validator/test/fixtures/compute_default_service_account/assets/data.json b/validator/test/fixtures/compute_default_service_account/assets/data.json new file mode 100644 index 000000000..0e2bd6720 --- /dev/null +++ b/validator/test/fixtures/compute_default_service_account/assets/data.json @@ -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": "66666666666-compute@developer.gserviceaccount.com", + "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": "77777776-compute@project.iam..gserviceaccount.com", + "scope": [ + ] + } + ], + "startRestricted": false, + "status": "TERMINATED", + "tags": { + "fingerprint": "42WmSpB8rSM=" + }, + "zone": "https://www.googleapis.com/compute/v1/projects/test-project/zones/us-east1-b" + } + } + } +] diff --git a/validator/test/fixtures/compute_default_service_account/constraints/data.yaml b/validator/test/fixtures/compute_default_service_account/constraints/data.yaml new file mode 100644 index 000000000..97e4fdb70 --- /dev/null +++ b/validator/test/fixtures/compute_default_service_account/constraints/data.yaml @@ -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: {} \ No newline at end of file