Skip to content

Commit

Permalink
feat: Support GCP PCI rules - Part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
m-pizarro committed May 17, 2022
1 parent e0a5599 commit 86be981
Show file tree
Hide file tree
Showing 22 changed files with 3,474 additions and 44 deletions.
8 changes: 4 additions & 4 deletions src/gcp/cis-1.2.0/rules/gcp-cis-1.2.0-3.7.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default {
- When ALL TCP ports are allowed in a rule, PORT does not have any value set (*NULL*)
- When ALL Protocols are allowed in a rule, PORT does not have any value set (*NULL*)`,
rationale: `GCP *Firewall Rule*s within a *VPC Network*. These rules apply to outgoing (egress) traffic from instances and incoming (ingress) traffic to instances in the network. Egress and ingress traffic flows are controlled even if the traffic stays within the network (for example, instance-to-instance communication). For an instance to have outgoing Internet access, the network must have a valid Internet gateway route or custom route whose destination IP is specified. This route simply defines the path to the Internet, to avoid the most general (0.0.0.0/0) destination IP Range specified from the Internet through RDP with the default *Port 3389*. Generic access from the Internet to a specific IP Range should be restricted.`,
rationale: 'GCP *Firewall Rule*s within a *VPC Network*. These rules apply to outgoing (egress) traffic from instances and incoming (ingress) traffic to instances in the network. Egress and ingress traffic flows are controlled even if the traffic stays within the network (for example, instance-to-instance communication). For an instance to have outgoing Internet access, the network must have a valid Internet gateway route or custom route whose destination IP is specified. This route simply defines the path to the Internet, to avoid the most general (0.0.0.0/0) destination IP Range specified from the Internet through RDP with the default *Port 3389*. Generic access from the Internet to a specific IP Range should be restricted.',
remediation: `**From the Console:**
1. Go to *VPC Network*.
Expand All @@ -48,7 +48,7 @@ export default {
1. Update RDP Firewall rule with new *SOURCE_RANGE* from the below command:
gcloud compute firewall-rules update FirewallName --allow=[PROTOCOL[:PORT[-PORT]],...] --source-ranges=[CIDR_RANGE,...]`,
references: [`https://cloud.google.com/vpc/docs/firewalls#blockedtraffic`],
references: ['https://cloud.google.com/vpc/docs/firewalls#blockedtraffic'],
gql: `{
querygcpFirewall(filter: {direction:{eq: "INGRESS"}}){
id
Expand Down Expand Up @@ -109,11 +109,11 @@ export default {
and: [
{
path: '[*].fromPort',
lessThanInclusive: 3986,
lessThanInclusive: 3389,
},
{
path: '[*].toPort',
greaterThanInclusive: 3986,
greaterThanInclusive: 3389,
},
],
},
Expand Down
30 changes: 15 additions & 15 deletions src/gcp/cis-1.2.0/tests/gcp-cis-1.2.0-3.x.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,8 @@ describe('CIS Google Cloud Platform Foundations: 1.2.0', () => {
expect(processedRule.result).toBe(expectedResult)
}

test('No Security Issue when there is an inbound rule with a random IPv4 address and port 3986', async () => {
await test37Rule(3986, 3986, '10.10.10.10/16', Result.PASS)
test('No Security Issue when there is an inbound rule with a random IPv4 address and port 3389', async () => {
await test37Rule(3389, 3389, '10.10.10.10/16', Result.PASS)
})

test('No Security Issue when there is an inbound rule with IPv4 wilcard address and port 80', async () => {
Expand All @@ -463,32 +463,32 @@ describe('CIS Google Cloud Platform Foundations: 1.2.0', () => {
await test37Rule(80, 80, ipV6WildcardAddress, Result.PASS)
})

test('No Security Issue when there is an inbound rule with a random IPv4 and a port range not including the port 3986', async () => {
test('No Security Issue when there is an inbound rule with a random IPv4 and a port range not including the port 3389', async () => {
await test37Rule(1000, 2000, '10.10.10.10/16', Result.PASS)
})

test('No Security Issue when there is an inbound rule with IPv4 wilcard address and a port range not including the port 3986', async () => {
test('No Security Issue when there is an inbound rule with IPv4 wilcard address and a port range not including the port 3389', async () => {
await test37Rule(1000, 2000, ipV4WildcardAddress, Result.PASS)
})

test('No Security Issue when there is an inbound rule with IPv6 wilcard address and a port range not including the port 3986', async () => {
test('No Security Issue when there is an inbound rule with IPv6 wilcard address and a port range not including the port 3389', async () => {
await test37Rule(1000, 2000, ipV6WildcardAddress, Result.PASS)
})

test('Security Issue when IPv4 wilcard address and port 3986 and tcp protocol', async () => {
await test37Rule(3986, 3986, ipV4WildcardAddress, Result.FAIL)
test('Security Issue when IPv4 wilcard address and port 3389 and tcp protocol', async () => {
await test37Rule(3389, 3389, ipV4WildcardAddress, Result.FAIL)
})

test('Security Issue when IPv4 wilcard address and port 3986 and all protocol', async () => {
await test37Rule(3986, 3986, ipV4WildcardAddress, Result.FAIL, 'all')
test('Security Issue when IPv4 wilcard address and port 3389 and all protocol', async () => {
await test37Rule(3389, 3389, ipV4WildcardAddress, Result.FAIL, 'all')
})

test('Security Issue when IPv6 wilcard address and port 3986 and tcp protocol', async () => {
await test37Rule(3986, 3986, ipV6WildcardAddress, Result.FAIL)
test('Security Issue when IPv6 wilcard address and port 3389 and tcp protocol', async () => {
await test37Rule(3389, 3389, ipV6WildcardAddress, Result.FAIL)
})

test('Security Issue when IPv6 wilcard address and port 3986 and all protocol', async () => {
await test37Rule(3986, 3986, ipV6WildcardAddress, Result.FAIL, 'all')
test('Security Issue when IPv6 wilcard address and port 3389 and all protocol', async () => {
await test37Rule(3389, 3389, ipV6WildcardAddress, Result.FAIL, 'all')
})

test('Security Issue when there is an inbound rule with IPv4 wilcard address and no port range is specified', async () => {
Expand All @@ -499,11 +499,11 @@ describe('CIS Google Cloud Platform Foundations: 1.2.0', () => {
await test37Rule(undefined, undefined, ipV6WildcardAddress, Result.FAIL)
})

test('Security Issue when there is an inbound rule with IPv4 wilcard address and port range includes the port 3986', async () => {
test('Security Issue when there is an inbound rule with IPv4 wilcard address and port range includes the port 3389', async () => {
await test37Rule(0, 4000, ipV4WildcardAddress, Result.FAIL)
})

test('Security Issue when there is an inbound rule with IPv6 wilcard address and port range includes the port 3986', async () => {
test('Security Issue when there is an inbound rule with IPv6 wilcard address and port range includes the port 3389', async () => {
await test37Rule(0, 4000, ipV6WildcardAddress, Result.FAIL)
})
})
Expand Down
23 changes: 17 additions & 6 deletions src/gcp/pci-dss-3.2.1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,21 @@ Policy Pack based on the [PCI DSS version 3.2.1](https://www.pcisecuritystandard
}
```

<!--
TODO: Uncomment table when rules available
## Available Ruleset
| Rule | Description |
| ------------ | ------------------------------------------------------------------------------------------------------ |
| - | - |
-->

| Rule | Description |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| iam-check-1 | IAM users should not have both KMS admin and any of the KMS encrypter/decrypter roles |
| iam-check-2 | IAM users should not have project-level "Service Account User" or "Service Account Token Creator" roles |
| monitoring-check-1 | Logging metric filter and alert for audit configuration changes should be configured |
| monitoring-check-2 | Logging metric filter and alert for Custom Role changes should be configured |
| monitoring-check-3 | Logging metric filter and alert for network changes should be configured |
| monitoring-check-4 | Logging metric filter and alert for network firewall rule changes should be configured |
| monitoring-check-5 | Logging metric filter and alert for network route changes should be configured |
| monitoring-check-6 | Logging metric filter and alert for project ownership assignments/changes should be configured |
| monitoring-check-7 | Logging metric filter and alert for SQL instance configuration changes should be configured |
| monitoring-check-8 | Logging metric filter and alert for Storage IAM permission changes should be configured |
| networking-check-1 | Network firewall rules should not permit ingress from 0.0.0.0/0 to port 22 (SSH) |
| networking-check-2 | Network firewall rules should not permit ingress from 0.0.0.0/0 to port 3389 (RDP) |
| networking-check-3 | The default network for a project should be deleted |
| networking-check-4 | Load balancer HTTPS or SSL proxy SSL policies should not have weak cipher suites |
30 changes: 29 additions & 1 deletion src/gcp/pci-dss-3.2.1/rules/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
import Gcp_PCI_DSS_321_IAM_1 from './pci-dss-3.2.1-iam-check-1'
import Gcp_PCI_DSS_321_IAM_2 from './pci-dss-3.2.1-iam-check-2'
import Gcp_PCI_DSS_321_Monitoring_1 from './pci-dss-3.2.1-monitoring-check-1'
import Gcp_PCI_DSS_321_Monitoring_2 from './pci-dss-3.2.1-monitoring-check-2'
import Gcp_PCI_DSS_321_Monitoring_3 from './pci-dss-3.2.1-monitoring-check-3'
import Gcp_PCI_DSS_321_Monitoring_4 from './pci-dss-3.2.1-monitoring-check-4'
import Gcp_PCI_DSS_321_Monitoring_5 from './pci-dss-3.2.1-monitoring-check-5'
import Gcp_PCI_DSS_321_Monitoring_6 from './pci-dss-3.2.1-monitoring-check-6'
import Gcp_PCI_DSS_321_Monitoring_7 from './pci-dss-3.2.1-monitoring-check-7'
import Gcp_PCI_DSS_321_Monitoring_8 from './pci-dss-3.2.1-monitoring-check-8'
import Gcp_PCI_DSS_321_Networking_1 from './pci-dss-3.2.1-networking-check-1'
import Gcp_PCI_DSS_321_Networking_2 from './pci-dss-3.2.1-networking-check-2'
import Gcp_PCI_DSS_321_Networking_3 from './pci-dss-3.2.1-networking-check-3'
import Gcp_PCI_DSS_321_Networking_4 from './pci-dss-3.2.1-networking-check-4'

export default [
// TODO: Add rules to export
Gcp_PCI_DSS_321_IAM_1,
Gcp_PCI_DSS_321_IAM_2,
Gcp_PCI_DSS_321_Monitoring_1,
Gcp_PCI_DSS_321_Monitoring_2,
Gcp_PCI_DSS_321_Monitoring_3,
Gcp_PCI_DSS_321_Monitoring_4,
Gcp_PCI_DSS_321_Monitoring_5,
Gcp_PCI_DSS_321_Monitoring_6,
Gcp_PCI_DSS_321_Monitoring_7,
Gcp_PCI_DSS_321_Monitoring_8,
Gcp_PCI_DSS_321_Networking_1,
Gcp_PCI_DSS_321_Networking_2,
Gcp_PCI_DSS_321_Networking_3,
Gcp_PCI_DSS_321_Networking_4,
]
67 changes: 67 additions & 0 deletions src/gcp/pci-dss-3.2.1/rules/pci-dss-3.2.1-iam-check-1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// GCP CIS 1.2.0 Rule equivalent 1.11
export default {
id: 'gcp-pci-dss-3.2.1-iam-check-1',
title: 'IAM check 1: IAM users should not have both KMS admin and any of the KMS encrypter/decrypter roles',

description: 'It is recommended that the principle of "Separation of Duties" is enforced while assigning KMS related roles to users.',

audit: `**From Console:**
1. Go to IAM & Admin/IAM by visiting https://console.cloud.google.com/iam-admin/iam
2. Ensure no member has the roles Cloud KMS Admin and any of the Cloud KMS CryptoKey Encrypter/Decrypter, Cloud KMS CryptoKey Encrypter, Cloud KMS CryptoKey Decrypter assigned.
**From Command Line:**
1. List all users and role assignments:
gcloud projects get-iam-policy PROJECT_ID
2. Ensure that there are no common users found in the member section for roles cloudkms.admin and any one of Cloud KMS CryptoKey Encrypter/Decrypter, Cloud KMS CryptoKey Encrypter, Cloud KMS CryptoKey Decrypter`,

rationale: `The built-in/predefined IAM role Cloud KMS Admin allows the user/identity to create, delete, and manage service account(s). The built-in/predefined IAM role Cloud KMS CryptoKey Encrypter/Decrypter allows the user/identity (with adequate privileges on concerned resources) to encrypt and decrypt data at rest using an encryption key(s).
The built-in/predefined IAM role Cloud KMS CryptoKey Encrypter allows the user/identity (with adequate privileges on concerned resources) to encrypt data at rest using an encryption key(s). The built-in/predefined IAM role Cloud KMS CryptoKey Decrypter allows the user/identity (with adequate privileges on concerned resources) to decrypt data at rest using an encryption key(s).
Separation of duties is the concept of ensuring that one individual does not have all necessary permissions to be able to complete a malicious action. In Cloud KMS, this could be an action such as using a key to access and decrypt data a user should not normally have access to. Separation of duties is a business control typically used in larger organizations, meant to help avoid security or privacy incidents and errors. It is considered best practice.
No user(s) should have Cloud KMS Admin and any of the Cloud KMS CryptoKey Encrypter/Decrypter, Cloud KMS CryptoKey Encrypter, Cloud KMS CryptoKey Decrypter roles assigned at the same time`,

remediation: `**From Console:**
1. Go to IAM & Admin/IAM using https://console.cloud.google.com/iam-admin/iam
2. For any member having Cloud KMS Admin and any of the Cloud KMS CryptoKey Encrypter/Decrypter, Cloud KMS CryptoKey Encrypter, Cloud KMS CryptoKey Decrypter roles granted assigned, click the Delete Bin icon to remove the role from the member.`,

references: ['https://cloud.google.com/kms/docs/separation-of-duties'],
gql: `{
querygcpIamPolicy {
id
__typename
bindings {
role
members
}
}
}`,
resource: 'querygcpIamPolicy[*]',
severity: 'unknown',
conditions: {
jq: `[({"member" : .bindings[].members[], "roles" : .bindings[].role}) ]
| group_by(.member)
| map({ "member" : .[].member, "roles" : map(.roles) })
| [.[]
| select(.roles
| contains(["roles/cloudkms.admin", "roles/cloudkms.cryptoKeyEncrypterDecrypter"])
or contains(["roles/cloudkms.admin", "roles/cloudkms.cryptoKeyEncrypter"])
or contains(["roles/cloudkms.admin", "roles/cloudkms.cryptoKeyDecrypter"]))]
| {"userHasInvalidRoles": ( (. | length) > 0)}`,
path: '@',
and: [
{
path: '@.userHasInvalidRoles',
notEqual: true,
},
],
},
}
Loading

0 comments on commit 86be981

Please sign in to comment.