Zum Inhalt

Forseti Sicherheit Cheat Blatt

generieren

Überblick

Forseti Security ist ein Open-Source-Sicherheitstoolkit für Google Cloud Platform (GCP), das umfassende Sicherheitsüberwachung, politische Durchsetzung und Compliance-Management bietet. Ursprünglich von Google entwickelt, hilft Forseti Security Organisationen, Sicherheit in ihren GCP-Umgebungen durch automatisiertes Scannen, politische Validierung und Echtzeitüberwachung zu erhalten. Die Plattform bietet Bestandsverwaltung, politische Durchsetzung und Verstöße, die für die Aufrechterhaltung einer sicheren und konformen Cloud-Infrastruktur unerlässlich sind.

RECHT Key Features: Echtzeit-Inventar-Scanning, Policy-forcement Engine, Compliance-Monitoring, Sicherheitsverletzungserkennung, automatisierte Abhilfe, Multi-Projekt-Unterstützung, Custom-Regel-Engine und Integration mit Cloud Security Command Center.

Installation und Inbetriebnahme

Voraussetzungen und Umweltschutz

```bash

System requirements check

echo "Checking system requirements for Forseti Security..."

Check Python installation (Python 3.6+ required)

if command -v python3 &> /dev/null; then python_version=$(python3 --version | awk '{print $2}') echo "✅ Python found: $python_version" else echo "❌ Python not found. Installing Python 3..." sudo apt update sudo apt install -y python3 python3-pip python3-venv fi

Check gcloud CLI installation

if command -v gcloud &> /dev/null; then gcloud_version=$(gcloud --version | head -n1) echo "✅ Google Cloud CLI found: $gcloud_version" else echo "❌ Google Cloud CLI not found. Installing gcloud..." curl https://sdk.cloud.google.com | bash exec -l $SHELL gcloud init fi

Check Terraform installation (for infrastructure setup)

if command -v terraform &> /dev/null; then terraform_version=$(terraform --version | head -n1) echo "✅ Terraform found: $terraform_version" else echo "❌ Terraform not found. Installing Terraform..." | wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg | echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install terraform fi

Check Docker installation (for containerized deployment)

if command -v docker &> /dev/null; then docker_version=$(docker --version) echo "✅ Docker found: $docker_version" else echo "❌ Docker not found. Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER fi

Verify installations

echo "Verifying installations..." python3 --version gcloud --version terraform --version docker --version

echo "Prerequisites check completed" ```_

GCP Projektaufbau und Authentifizierung

```bash

Set up GCP project for Forseti Security

export PROJECT_ID="your-forseti-project" export ORGANIZATION_ID="your-organization-id" export BILLING_ACCOUNT="your-billing-account"

Authenticate with Google Cloud

gcloud auth login gcloud auth application-default login

Create or select project

gcloud projects create $PROJECT_ID --organization=$ORGANIZATION_ID gcloud config set project $PROJECT_ID

Link billing account

gcloud billing projects link $PROJECT_ID --billing-account=$BILLING_ACCOUNT

Enable required APIs

echo "Enabling required GCP APIs..." gcloud services enable cloudasset.googleapis.com gcloud services enable cloudresourcemanager.googleapis.com gcloud services enable compute.googleapis.com gcloud services enable container.googleapis.com gcloud services enable iam.googleapis.com gcloud services enable logging.googleapis.com gcloud services enable monitoring.googleapis.com gcloud services enable securitycenter.googleapis.com gcloud services enable sql-component.googleapis.com gcloud services enable storage-api.googleapis.com gcloud services enable storage-component.googleapis.com

Wait for APIs to be enabled

echo "Waiting for APIs to be enabled..." sleep 30

Verify API enablement

gcloud services list --enabled --filter="name:cloudasset.googleapis.com OR name:cloudresourcemanager.googleapis.com"

Create Forseti service account

gcloud iam service-accounts create forseti-security \ --display-name="Forseti Security Service Account" \ --description="Service account for Forseti Security operations"

Get service account email

export FORSETI_SA_EMAIL="forseti-security@${PROJECT_ID}.iam.gserviceaccount.com"

Grant necessary permissions to Forseti service account

echo "Granting permissions to Forseti service account..."

Organization-level permissions

gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/browser"

gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/cloudasset.viewer"

gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/iam.securityReviewer"

gcloud organizations add-iam-policy-binding $ORGANIZATION_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/securitycenter.findingsEditor"

Project-level permissions

gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/cloudsql.client"

gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/compute.instanceAdmin"

gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$FORSETI_SA_EMAIL" \ --role="roles/storage.objectAdmin"

Create and download service account key

gcloud iam service-accounts keys create forseti-security-key.json \ --iam-account=$FORSETI_SA_EMAIL

echo "GCP project setup completed" echo "Service account email: $FORSETI_SA_EMAIL" echo "Service account key saved to: forseti-security-key.json" ```_

Infrastruktur Bereitstellung

```bash

Create Terraform configuration for Forseti Security infrastructure

mkdir -p forseti-terraform cd forseti-terraform

Create main Terraform configuration

cat > main.tf << 'EOF' terraform { required_version = ">= 0.14" required_providers { google = { source = "hashicorp/google" version = "~> 4.0" } google-beta = { source = "hashicorp/google-beta" version = "~> 4.0" } } }

provider "google" { project = var.project_id region = var.region zone = var.zone }

provider "google-beta" { project = var.project_id region = var.region zone = var.zone }

Variables

variable "project_id" { description = "GCP Project ID" type = string }

variable "organization_id" { description = "GCP Organization ID" type = string }

variable "region" { description = "GCP Region" type = string default = "us-central1" }

variable "zone" { description = "GCP Zone" type = string default = "us-central1-a" }

variable "forseti_version" { description = "Forseti Security version" type = string default = "v2.25.1" }

VPC Network for Forseti

resource "google_compute_network" "forseti_network" { name = "forseti-security-network" auto_create_subnetworks = false description = "VPC network for Forseti Security" }

resource "google_compute_subnetwork" "forseti_subnetwork" { name = "forseti-security-subnetwork" ip_cidr_range = "10.0.0.0/24" region = var.region network = google_compute_network.forseti_network.id description = "Subnetwork for Forseti Security" }

Firewall rules

resource "google_compute_firewall" "forseti_server_allow_grpc" { name = "forseti-server-allow-grpc" network = google_compute_network.forseti_network.name

allow { protocol = "tcp" ports = ["50051"] }

source_ranges = ["10.0.0.0/24"] target_tags = ["forseti-server"] description = "Allow gRPC communication to Forseti server" }

resource "google_compute_firewall" "forseti_allow_ssh" { name = "forseti-allow-ssh" network = google_compute_network.forseti_network.name

allow { protocol = "tcp" ports = ["22"] }

source_ranges = ["0.0.0.0/0"] target_tags = ["forseti-security"] description = "Allow SSH access to Forseti instances" }

Cloud SQL instance for Forseti database

resource "google_sql_database_instance" "forseti_database" { name = "forseti-security-db" database_version = "MYSQL_8_0" region = var.region deletion_protection = false

settings { tier = "db-n1-standard-1" activation_policy = "ALWAYS" availability_type = "ZONAL" backup_configuration { enabled = true start_time = "03:00" location = var.region binary_log_enabled = true transaction_log_retention_days = 7 }

database_flags {
  name  = "slow_query_log"
  value = "on"
}

ip_configuration {
  ipv4_enabled    = true
  private_network = google_compute_network.forseti_network.id
  require_ssl     = true

  authorized_networks {
    name  = "forseti-subnetwork"
    value = "10.0.0.0/24"
  }
}

maintenance_window {
  day          = 7
  hour         = 3
  update_track = "stable"
}

}

depends_on = [google_service_networking_connection.private_vpc_connection] }

Private service connection for Cloud SQL

resource "google_compute_global_address" "private_ip_address" { name = "forseti-private-ip-address" purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 network = google_compute_network.forseti_network.id }

resource "google_service_networking_connection" "private_vpc_connection" { network = google_compute_network.forseti_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_address.name] }

Forseti database

resource "google_sql_database" "forseti_database" { name = "forseti_security" instance = google_sql_database_instance.forseti_database.name }

Forseti database user

resource "google_sql_user" "forseti_user" { name = "forseti_security_user" instance = google_sql_database_instance.forseti_database.name password = random_password.forseti_db_password.result }

resource "random_password" "forseti_db_password" { length = 16 special = true }

Cloud Storage bucket for Forseti

resource "google_storage_bucket" "forseti_server_bucket" { name = "${var.project_id}-forseti-security-bucket" location = var.region force_destroy = true

uniform_bucket_level_access = true

versioning { enabled = true }

lifecycle_rule { condition { age = 30 } action { type = "Delete" } } }

Forseti Server VM instance

resource "google_compute_instance" "forseti_server" { name = "forseti-security-server" machine_type = "n1-standard-2" zone = var.zone

tags = ["forseti-server", "forseti-security"]

boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-2004-lts" size = 50 type = "pd-standard" } }

network_interface { network = google_compute_network.forseti_network.name subnetwork = google_compute_subnetwork.forseti_subnetwork.name

access_config {
  // Ephemeral public IP
}

}

service_account { email = google_service_account.forseti_server_sa.email scopes = ["cloud-platform"] }

metadata = { enable-oslogin = "TRUE" }

metadata_startup_script = templatefile("${path.module}/startup-script.sh", { project_id = var.project_id forseti_version = var.forseti_version db_host = google_sql_database_instance.forseti_database.private_ip_address db_name = google_sql_database.forseti_database.name db_user = google_sql_user.forseti_user.name db_password = google_sql_user.forseti_user.password bucket_name = google_storage_bucket.forseti_server_bucket.name organization_id = var.organization_id })

depends_on = [ google_sql_database_instance.forseti_database, google_storage_bucket.forseti_server_bucket ] }

Forseti Client VM instance

resource "google_compute_instance" "forseti_client" { name = "forseti-security-client" machine_type = "n1-standard-1" zone = var.zone

tags = ["forseti-client", "forseti-security"]

boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-2004-lts" size = 30 type = "pd-standard" } }

network_interface { network = google_compute_network.forseti_network.name subnetwork = google_compute_subnetwork.forseti_subnetwork.name

access_config {
  // Ephemeral public IP
}

}

service_account { email = google_service_account.forseti_client_sa.email scopes = ["cloud-platform"] }

metadata = { enable-oslogin = "TRUE" }

metadata_startup_script = templatefile("${path.module}/client-startup-script.sh", { project_id = var.project_id forseti_version = var.forseti_version server_ip = google_compute_instance.forseti_server.network_interface[0].network_ip }) }

Service accounts

resource "google_service_account" "forseti_server_sa" { account_id = "forseti-server-gcp-sa" display_name = "Forseti Server Service Account" description = "Service account for Forseti Security server" }

resource "google_service_account" "forseti_client_sa" { account_id = "forseti-client-gcp-sa" display_name = "Forseti Client Service Account" description = "Service account for Forseti Security client" }

IAM bindings for Forseti server service account

resource "google_organization_iam_member" "forseti_server_browser" { org_id = var.organization_id role = "roles/browser" member = "serviceAccount:${google_service_account.forseti_server_sa.email}" }

resource "google_organization_iam_member" "forseti_server_cloudasset_viewer" { org_id = var.organization_id role = "roles/cloudasset.viewer" member = "serviceAccount:${google_service_account.forseti_server_sa.email}" }

resource "google_organization_iam_member" "forseti_server_security_reviewer" { org_id = var.organization_id role = "roles/iam.securityReviewer" member = "serviceAccount:${google_service_account.forseti_server_sa.email}" }

resource "google_organization_iam_member" "forseti_server_security_center" { org_id = var.organization_id role = "roles/securitycenter.findingsEditor" member = "serviceAccount:${google_service_account.forseti_server_sa.email}" }

Project-level IAM bindings

resource "google_project_iam_member" "forseti_server_cloudsql_client" { project = var.project_id role = "roles/cloudsql.client" member = "serviceAccount:${google_service_account.forseti_server_sa.email}" }

resource "google_project_iam_member" "forseti_server_storage_admin" { project = var.project_id role = "roles/storage.objectAdmin" member = "serviceAccount:${google_service_account.forseti_server_sa.email}" }

Outputs

output "forseti_server_ip" { description = "Internal IP address of Forseti server" value = google_compute_instance.forseti_server.network_interface[0].network_ip }

output "forseti_server_external_ip" { description = "External IP address of Forseti server" value = google_compute_instance.forseti_server.network_interface[0].access_config[0].nat_ip }

output "forseti_client_ip" { description = "Internal IP address of Forseti client" value = google_compute_instance.forseti_client.network_interface[0].network_ip }

output "forseti_database_ip" { description = "Private IP address of Forseti database" value = google_sql_database_instance.forseti_database.private_ip_address }

output "forseti_bucket_name" { description = "Name of Forseti storage bucket" value = google_storage_bucket.forseti_server_bucket.name }

output "forseti_server_sa_email" { description = "Email of Forseti server service account" value = google_service_account.forseti_server_sa.email } EOF

Create startup script for Forseti server

cat > startup-script.sh << 'EOF'

!/bin/bash

Forseti Server Installation Script

set -e

Variables from Terraform

PROJECT_ID="${project_id}" FORSETI_VERSION="${forseti_version}" DB_HOST="${db_host}" DB_NAME="${db_name}" DB_USER="${db_user}" DB_PASSWORD="${db_password}" BUCKET_NAME="${bucket_name}" ORGANIZATION_ID="${organization_id}"

Update system

apt-get update apt-get install -y python3 python3-pip python3-venv git mysql-client

Create forseti user

useradd -m -s /bin/bash forseti usermod -aG sudo forseti

Install Forseti Security

cd /home/forseti git clone https://github.com/forseti-security/forseti-security.git cd forseti-security git checkout $FORSETI_VERSION

Create virtual environment

python3 -m venv forseti-env source forseti-env/bin/activate

Install dependencies

pip install --upgrade pip pip install -r requirements.txt pip install -e .

Create Forseti configuration directory

mkdir -p /home/forseti/forseti-security/configs

Create Forseti server configuration

cat > /home/forseti/forseti-security/configs/forseti_conf_server.yaml << EOFCONFIG global: # Database configuration db_host: $DB_HOST db_user: $DB_USER db_name: $DB_NAME db_password: $DB_PASSWORD

# GCS bucket for Forseti data
bucket_name: $BUCKET_NAME

# Email notification settings
email_recipient: admin@company.com
email_sender: forseti-noreply@$PROJECT_ID.iam.gserviceaccount.com
sendgrid_api_key: ""

# Organization and project settings
organization_id: $ORGANIZATION_ID

inventory: # Inventory configuration gcs_summary_path: gs://$BUCKET_NAME/inventory_summary.json

# Root resource to start inventory from
root_resource_id: $ORGANIZATION_ID

# Inventory modules to enable
api_quota_enabled: true
cai_enabled: true

scanner: # Scanner configuration enabled_scanners: - audit_logging - bigquery - blacklist - bucket_acl - cloudsql_acl - enabled_apis - firewall_rule - forwarding_rule - group - iam_policy - iap - instance_network_interface - ke_cluster - ke_node_pool - lien - location - log_sink - resource - service_account_key

# Scanner output path
output_path: gs://$BUCKET_NAME/scanner_violations

# Violation configs
rules_path: /home/forseti/forseti-security/rules

notifier: # Notification configuration enabled: true

# Notification channels
email_enabled: true
gcs_enabled: true
cscc_enabled: true

# CSCC (Cloud Security Command Center) settings
cscc_source_id: ""

# Violation summary
violation_summary_enabled: true

explain: # Explain configuration enabled: true

model: # Model configuration enabled: true

# Model location
model_location: gs://$BUCKET_NAME/model

EOFCONFIG

Set up database

mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME < install/gcp/scripts/create_forseti_tables.sql

Create systemd service for Forseti server

cat > /etc/systemd/system/forseti-server.service << EOFSERVICE [Unit] Description=Forseti Security Server After=network.target

[Service] Type=simple User=forseti Group=forseti WorkingDirectory=/home/forseti/forseti-security Environment=PATH=/home/forseti/forseti-security/forseti-env/bin ExecStart=/home/forseti/forseti-security/forseti-env/bin/python -m google.cloud.forseti.services.server --config_file_path=/home/forseti/forseti-security/configs/forseti_conf_server.yaml Restart=always RestartSec=10

[Install] WantedBy=multi-user.target EOFSERVICE

Set permissions

chown -R forseti:forseti /home/forseti chmod +x /home/forseti/forseti-security/forseti-env/bin/*

Enable and start Forseti server

systemctl daemon-reload systemctl enable forseti-server systemctl start forseti-server

Create log rotation

cat > /etc/logrotate.d/forseti << EOFLOGROTATE /var/log/forseti/*.log { daily missingok rotate 30 compress delaycompress notifempty create 644 forseti forseti postrotate systemctl reload forseti-server endscript } EOFLOGROTATE

echo "Forseti Security server installation completed" EOF

Create startup script for Forseti client

cat > client-startup-script.sh << 'EOF'

!/bin/bash

Forseti Client Installation Script

set -e

Variables from Terraform

PROJECT_ID="${project_id}" FORSETI_VERSION="${forseti_version}" SERVER_IP="${server_ip}"

Update system

apt-get update apt-get install -y python3 python3-pip python3-venv git

Create forseti user

useradd -m -s /bin/bash forseti usermod -aG sudo forseti

Install Forseti Security client

cd /home/forseti git clone https://github.com/forseti-security/forseti-security.git cd forseti-security git checkout $FORSETI_VERSION

Create virtual environment

python3 -m venv forseti-env source forseti-env/bin/activate

Install dependencies

pip install --upgrade pip pip install -r requirements.txt pip install -e .

Create Forseti client configuration

mkdir -p /home/forseti/forseti-security/configs

cat > /home/forseti/forseti-security/configs/forseti_conf_client.yaml << EOFCONFIG server_ip: $SERVER_IP server_port: 50051 EOFCONFIG

Set permissions

chown -R forseti:forseti /home/forseti

echo "Forseti Security client installation completed" EOF

Create terraform.tfvars file

cat > terraform.tfvars << EOF project_id = "$PROJECT_ID" organization_id = "$ORGANIZATION_ID" region = "us-central1" zone = "us-central1-a" forseti_version = "v2.25.1" EOF

Initialize and apply Terraform

terraform init terraform plan terraform apply -auto-approve

echo "Forseti Security infrastructure deployment completed" ```_

Einsatz von Docker

```bash

Create Docker Compose setup for Forseti Security

mkdir -p forseti-docker cd forseti-docker

Create Docker Compose file

cat > docker-compose.yml << 'EOF' version: '3.8'

services: # MySQL Database for Forseti forseti-db: image: mysql:8.0 container_name: forseti-mysql environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: forseti_security MYSQL_USER: forseti_security_user MYSQL_PASSWORD: forseti123 ports: - "3306:3306" volumes: - forseti_mysql_data:/var/lib/mysql - ./init-scripts:/docker-entrypoint-initdb.d networks: - forseti-network command: --default-authentication-plugin=mysql_native_password

# Forseti Security Server forseti-server: build: context: . dockerfile: Dockerfile.server container_name: forseti-server depends_on: - forseti-db environment: - FORSETI_DB_HOST=forseti-db - FORSETI_DB_PORT=3306 - FORSETI_DB_NAME=forseti_security - FORSETI_DB_USER=forseti_security_user - FORSETI_DB_PASSWORD=forseti123 - GOOGLE_APPLICATION_CREDENTIALS=/app/credentials/service-account.json - FORSETI_ORGANIZATION_ID=${ORGANIZATION_ID} - FORSETI_PROJECT_ID=${PROJECT_ID} ports: - "50051:50051" volumes: - ./config:/app/config - ./credentials:/app/credentials - ./rules:/app/rules - ./logs:/app/logs networks: - forseti-network

# Forseti Security Client forseti-client: build: context: . dockerfile: Dockerfile.client container_name: forseti-client depends_on: - forseti-server environment: - FORSETI_SERVER_HOST=forseti-server - FORSETI_SERVER_PORT=50051 - GOOGLE_APPLICATION_CREDENTIALS=/app/credentials/service-account.json volumes: - ./config:/app/config - ./credentials:/app/credentials - ./logs:/app/logs networks: - forseti-network stdin_open: true tty: true

volumes: forseti_mysql_data:

networks: forseti-network: driver: bridge EOF

Create Dockerfile for Forseti server

cat > Dockerfile.server << 'EOF' FROM python:3.8-slim

Install system dependencies

RUN apt-get update && apt-get install -y \ git \ mysql-client \ && rm -rf /var/lib/apt/lists/*

Create app directory

WORKDIR /app

Clone Forseti Security

RUN git clone https://github.com/forseti-security/forseti-security.git . RUN git checkout v2.25.1

Install Python dependencies

RUN pip install --upgrade pip RUN pip install -r requirements.txt RUN pip install -e .

Create necessary directories

RUN mkdir -p /app/config /app/credentials /app/rules /app/logs

Copy configuration files

COPY config/ /app/config/ COPY rules/ /app/rules/

Set permissions

RUN chmod +x /app/google/cloud/forseti/services/server.py

Expose gRPC port

EXPOSE 50051

Start Forseti server

CMD ["python", "-m", "google.cloud.forseti.services.server", "--config_file_path=/app/config/forseti_conf_server.yaml"] EOF

Create Dockerfile for Forseti client

cat > Dockerfile.client << 'EOF' FROM python:3.8-slim

Install system dependencies

RUN apt-get update && apt-get install -y \ git \ && rm -rf /var/lib/apt/lists/*

Create app directory

WORKDIR /app

Clone Forseti Security

RUN git clone https://github.com/forseti-security/forseti-security.git . RUN git checkout v2.25.1

Install Python dependencies

RUN pip install --upgrade pip RUN pip install -r requirements.txt RUN pip install -e .

Create necessary directories

RUN mkdir -p /app/config /app/credentials /app/logs

Copy configuration files

COPY config/ /app/config/

Start bash shell for interactive use

CMD ["/bin/bash"] EOF

Create configuration directory and files

mkdir -p config credentials rules logs init-scripts

Create Forseti server configuration

cat > config/forseti_conf_server.yaml << 'EOF' global: # Database configuration db_host: forseti-db db_user: forseti_security_user db_name: forseti_security db_password: forseti123

# Email notification settings
email_recipient: admin@company.com
email_sender: forseti-noreply@company.com
sendgrid_api_key: ""

# Organization and project settings
organization_id: "123456789012"

inventory: # Inventory configuration root_resource_id: "123456789012"

# Inventory modules to enable
api_quota_enabled: true
cai_enabled: true

scanner: # Scanner configuration enabled_scanners: - audit_logging - bigquery - blacklist - bucket_acl - cloudsql_acl - enabled_apis - firewall_rule - forwarding_rule - group - iam_policy - iap - instance_network_interface - ke_cluster - ke_node_pool - lien - location - log_sink - resource - service_account_key

# Violation configs
rules_path: /app/rules

notifier: # Notification configuration enabled: true

# Notification channels
email_enabled: true
gcs_enabled: false
cscc_enabled: false

# Violation summary
violation_summary_enabled: true

explain: # Explain configuration enabled: true

model: # Model configuration enabled: true EOF

Create Forseti client configuration

cat > config/forseti_conf_client.yaml << 'EOF' server_ip: forseti-server server_port: 50051 EOF

Create MySQL initialization script

cat > init-scripts/01-init-forseti.sql << 'EOF' -- Forseti Security Database Initialization

USE forseti_security;

-- Create tables for Forseti Security CREATE TABLE IF NOT EXISTS violations ( id BIGINT AUTO_INCREMENT PRIMARY KEY, resource_id VARCHAR(255), resource_type VARCHAR(255), rule_name VARCHAR(255), rule_index INT, violation_type VARCHAR(255), violation_data TEXT, resource_data TEXT, created_at_datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

CREATE TABLE IF NOT EXISTS inventory ( id BIGINT AUTO_INCREMENT PRIMARY KEY, inventory_index_id BIGINT, inventory_type VARCHAR(255), resource_data TEXT, created_at_datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

CREATE TABLE IF NOT EXISTS inventory_index ( id BIGINT AUTO_INCREMENT PRIMARY KEY, inventory_index_id BIGINT UNIQUE, completed_at_datetime TIMESTAMP, created_at_datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP, count_objects INT DEFAULT 0, schema_version VARCHAR(255) );

-- Insert sample data INSERT INTO inventory_index (inventory_index_id, completed_at_datetime, count_objects, schema_version) VALUES (1, NOW(), 0, '2.25.1');

COMMIT; EOF

Create sample rules directory

mkdir -p rules

Create sample security rules

cat > rules/firewall_rules.yaml << 'EOF' rules: - name: 'Firewall rule allows all traffic' mode: blacklist resource: - type: firewall_rule filters: - key: direction op: eq value: INGRESS - key: sourceRanges op: contains value: '0.0.0.0/0' - key: allowed.ports op: contains value: '' actions: - type: add_to_whitelist value: 'firewall-rule-' EOF

cat > rules/iam_rules.yaml << 'EOF' rules: - name: 'Service account has too many roles' mode: blacklist resource: - type: iam_policy filters: - key: bindings.members op: regex value: 'serviceAccount:.' - key: bindings.role op: regex value: 'roles/.' actions: - type: add_to_whitelist value: 'serviceAccount:@.iam.gserviceaccount.com' EOF

Create environment file

cat > .env << EOF PROJECT_ID=your-project-id ORGANIZATION_ID=your-organization-id EOF

Start Forseti with Docker Compose

echo "Starting Forseti Security with Docker Compose..." docker-compose up -d

Wait for services to start

echo "Waiting for services to start..." sleep 60

Check service status

docker-compose ps

Test connectivity

echo "Testing service connectivity..." docker-compose exec forseti-db mysql -u forseti_security_user -pforseti123 -e "SELECT 1" docker-compose logs forseti-server | tail -20

echo "Forseti Security Docker deployment completed" echo "Access Forseti server at: localhost:50051" echo "Connect to client: docker-compose exec forseti-client /bin/bash" ```_

Konfiguration und Regelverwaltung

Grundkonfiguration

```bash

Create Forseti configuration management script

cat > configure_forseti.sh << 'EOF'

!/bin/bash

Forseti Security Configuration Management

FORSETI_HOME=${FORSETI_HOME:-/home/forseti/forseti-security} CONFIG_DIR="$FORSETI_HOME/configs" RULES_DIR="$FORSETI_HOME/rules"

Create directories

mkdir -p "$CONFIG_DIR" "$RULES_DIR"

Function to configure inventory settings

configure_inventory() { echo "Configuring Forseti inventory settings..."

cat > "$CONFIG_DIR/inventory_config.yaml" << 'INVCONFIG'

Forseti Inventory Configuration

inventory: # Root resource configuration root_resource_id: "organizations/123456789012"

# Inventory modules
api_quota_enabled: true
cai_enabled: true

# Resource types to inventory
resource_types:
    - organization
    - folder
    - project
    - compute_instance
    - compute_disk
    - compute_network
    - compute_subnetwork
    - compute_firewall
    - storage_bucket
    - cloudsql_instance
    - iam_policy
    - service_account
    - service_account_key
    - bigquery_dataset
    - bigquery_table
    - kubernetes_cluster
    - kubernetes_node_pool

# Inventory frequency (in seconds)
inventory_frequency: 3600

# Parallel processing
max_workers: 10

# Timeout settings
inventory_timeout: 1800

# Output settings
output_format: json
gcs_summary_path: gs://forseti-bucket/inventory_summary.json

INVCONFIG

echo "Inventory configuration completed"

}

Function to configure scanner settings

configure_scanner() { echo "Configuring Forseti scanner settings..."

cat > "$CONFIG_DIR/scanner_config.yaml" << 'SCANCONFIG'

Forseti Scanner Configuration

scanner: # Enabled scanners enabled_scanners: - audit_logging - bigquery - blacklist - bucket_acl - cloudsql_acl - enabled_apis - firewall_rule - forwarding_rule - group - iam_policy - iap - instance_network_interface - ke_cluster - ke_node_pool - lien - location - log_sink - resource - service_account_key

# Scanner frequency (in seconds)
scanner_frequency: 7200

# Output settings
output_path: gs://forseti-bucket/scanner_violations

# Violation retention (in days)
violation_retention_days: 30

# Scanner timeout (in seconds)
scanner_timeout: 3600

# Parallel processing
max_scanner_processes: 5

# Rules configuration
rules_path: /home/forseti/forseti-security/rules

# Whitelist configuration
whitelist_enabled: true
whitelist_path: /home/forseti/forseti-security/rules/whitelist.yaml

SCANCONFIG

echo "Scanner configuration completed"

}

Function to configure notifier settings

configure_notifier() { echo "Configuring Forseti notifier settings..."

cat > "$CONFIG_DIR/notifier_config.yaml" << 'NOTIFYCONFIG'

Forseti Notifier Configuration

notifier: # Notification enabled enabled: true

# Email notifications
email_enabled: true
email_recipient: security-team@company.com
email_sender: forseti-noreply@company.com

# SendGrid configuration
sendgrid_api_key: ""

# GCS notifications
gcs_enabled: true
gcs_path: gs://forseti-bucket/notifications

# Cloud Security Command Center
cscc_enabled: true
cscc_source_id: "organizations/123456789012/sources/1234567890123456789"

# Slack notifications
slack_enabled: false
slack_webhook_url: ""

# Notification frequency
notification_frequency: 86400

# Violation summary
violation_summary_enabled: true

# Notification filters
notification_filters:
    - severity: HIGH
      enabled: true
    - severity: MEDIUM
      enabled: true
    - severity: LOW
      enabled: false

# Template configuration
email_template_path: /home/forseti/forseti-security/templates/email_template.html

NOTIFYCONFIG

echo "Notifier configuration completed"

}

Function to configure explain settings

configure_explain() { echo "Configuring Forseti explain settings..."

cat > "$CONFIG_DIR/explain_config.yaml" << 'EXPLAINCONFIG'

Forseti Explain Configuration

explain: # Explain enabled enabled: true

# Explain timeout (in seconds)
explain_timeout: 300

# Maximum number of policies to explain
max_policies: 1000

# Output format
output_format: json

# Cache settings
cache_enabled: true
cache_ttl: 3600

# Explain frequency (in seconds)
explain_frequency: 21600

EXPLAINCONFIG

echo "Explain configuration completed"

}

Function to configure model settings

configure_model() { echo "Configuring Forseti model settings..."

cat > "$CONFIG_DIR/model_config.yaml" << 'MODELCONFIG'

Forseti Model Configuration

model: # Model enabled enabled: true

# Model location
model_location: gs://forseti-bucket/model

# Model timeout (in seconds)
model_timeout: 1800

# Model frequency (in seconds)
model_frequency: 3600

# Model retention (in days)
model_retention_days: 7

# Model verification
verify_policy_awesomeness: true

MODELCONFIG

echo "Model configuration completed"

}

Main configuration function

main() { echo "Starting Forseti Security configuration..."

configure_inventory
configure_scanner
configure_notifier
configure_explain
configure_model

# Set permissions
chmod -R 755 "$CONFIG_DIR"

echo "Forseti Security configuration completed successfully"
echo "Configuration files created in: $CONFIG_DIR"

}

Run configuration

main "$@" EOF

chmod +x configure_forseti.sh ./configure_forseti.sh ```_

Erstellung der Zollregel

```python

!/usr/bin/env python3

Forseti Security Custom Rule Creation

import yaml import json import os from datetime import datetime

class ForsetiRuleManager: """Manage Forseti Security custom rules"""

def __init__(self, rules_directory='/home/forseti/forseti-security/rules'):
    self.rules_directory = rules_directory
    self.ensure_rules_directory()

def ensure_rules_directory(self):
    """Ensure rules directory exists"""
    os.makedirs(self.rules_directory, exist_ok=True)

def create_firewall_rules(self):
    """Create firewall security rules"""

    firewall_rules = {
        'rules': [
            {
                'name': 'Firewall allows all traffic from internet',
                'mode': 'blacklist',
                'resource': [{'type': 'firewall_rule'}],
                'filters': [
                    {'key': 'direction', 'op': 'eq', 'value': 'INGRESS'},
                    {'key': 'sourceRanges', 'op': 'contains', 'value': '0.0.0.0/0'},
                    {'key': 'allowed.ports', 'op': 'contains', 'value': '*'}
                ],
                'actions': [
                    {'type': 'add_to_whitelist', 'value': 'firewall-rule-web-*'}
                ]
            },
            {
                'name': 'Firewall allows SSH from internet',
                'mode': 'blacklist',
                'resource': [{'type': 'firewall_rule'}],
                'filters': [
                    {'key': 'direction', 'op': 'eq', 'value': 'INGRESS'},
                    {'key': 'sourceRanges', 'op': 'contains', 'value': '0.0.0.0/0'},
                    {'key': 'allowed.ports', 'op': 'contains', 'value': '22'}
                ]
            },
            {
                'name': 'Firewall allows RDP from internet',
                'mode': 'blacklist',
                'resource': [{'type': 'firewall_rule'}],
                'filters': [
                    {'key': 'direction', 'op': 'eq', 'value': 'INGRESS'},
                    {'key': 'sourceRanges', 'op': 'contains', 'value': '0.0.0.0/0'},
                    {'key': 'allowed.ports', 'op': 'contains', 'value': '3389'}
                ]
            }
        ]
    }

    with open(f"{self.rules_directory}/firewall_rules.yaml", 'w') as f:
        yaml.dump(firewall_rules, f, default_flow_style=False)

    print("Firewall rules created successfully")

def create_iam_rules(self):
    """Create IAM security rules"""

    iam_rules = {
        'rules': [
            {
                'name': 'Service account has owner role',
                'mode': 'blacklist',
                'resource': [{'type': 'iam_policy'}],
                'filters': [
                    {'key': 'bindings.members', 'op': 'regex', 'value': 'serviceAccount:.*'},
                    {'key': 'bindings.role', 'op': 'eq', 'value': 'roles/owner'}
                ]
            },
            {
                'name': 'User has primitive roles',
                'mode': 'blacklist',
                'resource': [{'type': 'iam_policy'}],
                'filters': [
                    {'key': 'bindings.members', 'op': 'regex', 'value': 'user:.*'},

| {'key': 'bindings.role', 'op': 'regex', 'value': 'roles/(owner | editor | viewer)'} | ], 'actions': [ {'type': 'add_to_whitelist', 'value': 'user:admin@company.com'} ] }, { 'name': 'Service account key is old', 'mode': 'blacklist', 'resource': [{'type': 'service_account_key'}], 'filters': [ {'key': 'validAfterTime', 'op': 'older_than', 'value': '90d'} ] } ] }

    with open(f"{self.rules_directory}/iam_rules.yaml", 'w') as f:
        yaml.dump(iam_rules, f, default_flow_style=False)

    print("IAM rules created successfully")

def create_storage_rules(self):
    """Create Cloud Storage security rules"""

    storage_rules = {
        'rules': [
            {
                'name': 'Storage bucket is publicly readable',
                'mode': 'blacklist',
                'resource': [{'type': 'bucket_acl'}],
                'filters': [
                    {'key': 'entity', 'op': 'eq', 'value': 'allUsers'},
                    {'key': 'role', 'op': 'eq', 'value': 'READER'}
                ],
                'actions': [
                    {'type': 'add_to_whitelist', 'value': 'public-website-*'}
                ]
            },
            {
                'name': 'Storage bucket is publicly writable',
                'mode': 'blacklist',
                'resource': [{'type': 'bucket_acl'}],
                'filters': [
                    {'key': 'entity', 'op': 'eq', 'value': 'allUsers'},
                    {'key': 'role', 'op': 'eq', 'value': 'WRITER'}
                ]
            },
            {
                'name': 'Storage bucket allows authenticated users',
                'mode': 'blacklist',
                'resource': [{'type': 'bucket_acl'}],
                'filters': [
                    {'key': 'entity', 'op': 'eq', 'value': 'allAuthenticatedUsers'}
                ]
            }
        ]
    }

    with open(f"{self.rules_directory}/storage_rules.yaml", 'w') as f:
        yaml.dump(storage_rules, f, default_flow_style=False)

    print("Storage rules created successfully")

def create_compute_rules(self):
    """Create Compute Engine security rules"""

    compute_rules = {
        'rules': [
            {
                'name': 'Instance has public IP',
                'mode': 'blacklist',
                'resource': [{'type': 'instance'}],
                'filters': [
                    {'key': 'networkInterfaces.accessConfigs.type', 'op': 'eq', 'value': 'ONE_TO_ONE_NAT'}
                ],
                'actions': [
                    {'type': 'add_to_whitelist', 'value': 'bastion-*'},
                    {'type': 'add_to_whitelist', 'value': 'web-*'}
                ]
            },
            {
                'name': 'Instance allows HTTP traffic',
                'mode': 'blacklist',
                'resource': [{'type': 'instance'}],
                'filters': [
                    {'key': 'tags.items', 'op': 'contains', 'value': 'http-server'}
                ]
            },
            {
                'name': 'Instance has default service account',
                'mode': 'blacklist',
                'resource': [{'type': 'instance'}],
                'filters': [
                    {'key': 'serviceAccounts.email', 'op': 'regex', 'value': '.*-compute@developer.gserviceaccount.com'}
                ]
            }
        ]
    }

    with open(f"{self.rules_directory}/compute_rules.yaml", 'w') as f:
        yaml.dump(compute_rules, f, default_flow_style=False)

    print("Compute rules created successfully")

def create_cloudsql_rules(self):
    """Create Cloud SQL security rules"""

    cloudsql_rules = {
        'rules': [
            {
                'name': 'Cloud SQL instance allows public access',
                'mode': 'blacklist',
                'resource': [{'type': 'cloudsql_instance'}],
                'filters': [
                    {'key': 'settings.ipConfiguration.authorizedNetworks.value', 'op': 'eq', 'value': '0.0.0.0/0'}
                ]
            },
            {
                'name': 'Cloud SQL instance has SSL disabled',
                'mode': 'blacklist',
                'resource': [{'type': 'cloudsql_instance'}],
                'filters': [
                    {'key': 'settings.ipConfiguration.requireSsl', 'op': 'eq', 'value': False}
                ]
            },
            {
                'name': 'Cloud SQL instance has backup disabled',
                'mode': 'blacklist',
                'resource': [{'type': 'cloudsql_instance'}],
                'filters': [
                    {'key': 'settings.backupConfiguration.enabled', 'op': 'eq', 'value': False}
                ]
            }
        ]
    }

    with open(f"{self.rules_directory}/cloudsql_rules.yaml", 'w') as f:
        yaml.dump(cloudsql_rules, f, default_flow_style=False)

    print("Cloud SQL rules created successfully")

def create_kubernetes_rules(self):
    """Create Kubernetes security rules"""

    kubernetes_rules = {
        'rules': [
            {
                'name': 'GKE cluster has legacy ABAC enabled',
                'mode': 'blacklist',
                'resource': [{'type': 'ke_cluster'}],
                'filters': [
                    {'key': 'legacyAbac.enabled', 'op': 'eq', 'value': True}
                ]
            },
            {
                'name': 'GKE cluster has basic authentication enabled',
                'mode': 'blacklist',
                'resource': [{'type': 'ke_cluster'}],
                'filters': [
                    {'key': 'masterAuth.username', 'op': 'ne', 'value': ''}
                ]
            },
            {
                'name': 'GKE cluster has client certificate enabled',
                'mode': 'blacklist',
                'resource': [{'type': 'ke_cluster'}],
                'filters': [
                    {'key': 'masterAuth.clientCertificateConfig.issueClientCertificate', 'op': 'eq', 'value': True}
                ]
            },
            {
                'name': 'GKE node pool has legacy metadata endpoints enabled',
                'mode': 'blacklist',
                'resource': [{'type': 'ke_node_pool'}],
                'filters': [
                    {'key': 'config.metadata.disable-legacy-endpoints', 'op': 'ne', 'value': 'true'}
                ]
            }
        ]
    }

    with open(f"{self.rules_directory}/kubernetes_rules.yaml", 'w') as f:
        yaml.dump(kubernetes_rules, f, default_flow_style=False)

    print("Kubernetes rules created successfully")

def create_whitelist_rules(self):
    """Create whitelist configuration"""

    whitelist_config = {
        'whitelist': {
            'firewall_rule': [
                'firewall-rule-web-allow-80',
                'firewall-rule-web-allow-443',
                'firewall-rule-bastion-ssh'
            ],
            'instance': [
                'bastion-host-prod',
                'web-server-prod-*'
            ],
            'bucket_acl': [
                'public-website-bucket',
                'public-assets-bucket'
            ],
            'iam_policy': [
                'user:admin@company.com',
                'serviceAccount:terraform@project.iam.gserviceaccount.com'
            ]
        }
    }

    with open(f"{self.rules_directory}/whitelist.yaml", 'w') as f:
        yaml.dump(whitelist_config, f, default_flow_style=False)

    print("Whitelist configuration created successfully")

def create_custom_rule(self, rule_name, resource_type, filters, mode='blacklist', actions=None):
    """Create a custom rule"""

    rule = {
        'rules': [
            {
                'name': rule_name,
                'mode': mode,
                'resource': [{'type': resource_type}],
                'filters': filters
            }
        ]
    }

    if actions:
        rule['rules'][0]['actions'] = actions

    filename = f"{rule_name.lower().replace(' ', '_')}_rule.yaml"
    with open(f"{self.rules_directory}/{filename}", 'w') as f:
        yaml.dump(rule, f, default_flow_style=False)

    print(f"Custom rule '{rule_name}' created successfully: {filename}")

def validate_rule(self, rule_file):
    """Validate rule syntax"""

    try:
        with open(rule_file, 'r') as f:
            rule_data = yaml.safe_load(f)

        # Basic validation
        if 'rules' not in rule_data:
            return False, "Missing 'rules' key"

        for rule in rule_data['rules']:
            required_keys = ['name', 'mode', 'resource', 'filters']
            for key in required_keys:
                if key not in rule:
                    return False, f"Missing required key: {key}"

            # Validate mode
            if rule['mode'] not in ['blacklist', 'whitelist']:
                return False, f"Invalid mode: {rule['mode']}"

            # Validate resource type
            valid_types = [
                'firewall_rule', 'instance', 'bucket_acl', 'iam_policy',
                'service_account_key', 'cloudsql_instance', 'ke_cluster', 'ke_node_pool'
            ]

            for resource in rule['resource']:
                if resource['type'] not in valid_types:
                    return False, f"Invalid resource type: {resource['type']}"

        return True, "Rule validation passed"

    except Exception as e:
        return False, f"Validation error: {e}"

def list_rules(self):
    """List all rule files"""

    rule_files = []
    for file in os.listdir(self.rules_directory):
        if file.endswith('.yaml') or file.endswith('.yml'):
            rule_files.append(file)

    return rule_files

def generate_all_rules(self):
    """Generate all default security rules"""

    print("Generating Forseti Security rules...")

    self.create_firewall_rules()
    self.create_iam_rules()
    self.create_storage_rules()
    self.create_compute_rules()
    self.create_cloudsql_rules()
    self.create_kubernetes_rules()
    self.create_whitelist_rules()

    print(f"All rules generated in: {self.rules_directory}")

    # List generated rules
    rules = self.list_rules()
    print(f"Generated {len(rules)} rule files:")
    for rule in rules:
        print(f"  - {rule}")

def main(): """Main function for rule management"""

import argparse

parser = argparse.ArgumentParser(description='Forseti Security Rule Manager')
parser.add_argument('--action', choices=['generate', 'validate', 'list', 'custom'], 
                   required=True, help='Action to perform')
parser.add_argument('--rules-dir', default='/home/forseti/forseti-security/rules', 
                   help='Rules directory path')
parser.add_argument('--rule-file', help='Rule file to validate')
parser.add_argument('--rule-name', help='Custom rule name')
parser.add_argument('--resource-type', help='Resource type for custom rule')
parser.add_argument('--filters', help='Filters for custom rule (JSON format)')

args = parser.parse_args()

manager = ForsetiRuleManager(args.rules_dir)

if args.action == 'generate':
    manager.generate_all_rules()

elif args.action == 'validate' and args.rule_file:
    valid, message = manager.validate_rule(args.rule_file)
    print(f"Validation result: {message}")
    exit(0 if valid else 1)

elif args.action == 'list':
    rules = manager.list_rules()
    print(f"Found {len(rules)} rule files:")
    for rule in rules:
        print(f"  - {rule}")

elif args.action == 'custom':
    if not all([args.rule_name, args.resource_type, args.filters]):
        print("Custom rule requires: --rule-name, --resource-type, --filters")
        exit(1)

    try:
        filters = json.loads(args.filters)
        manager.create_custom_rule(args.rule_name, args.resource_type, filters)
    except json.JSONDecodeError:
        print("Invalid JSON format for filters")
        exit(1)

else:
    parser.print_help()

if name == "main": main() ```_

Überwachung und Berichterstattung

Compliance Monitoring

```python

!/usr/bin/env python3

Forseti Security Monitoring and Reporting

import mysql.connector import json import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from datetime import datetime, timedelta import smtplib from email.mime.text import MimeText from email.mime.multipart import MimeMultipart from email.mime.base import MimeBase from email import encoders import logging from google.cloud import storage from google.cloud import securitycenter

class ForsetiMonitor: """Monitor and report on Forseti Security findings"""

def __init__(self, config):
    self.config = config
    self.setup_logging()
    self.setup_connections()

def setup_logging(self):
    """Setup logging configuration"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler('forseti_monitor.log'),
            logging.StreamHandler()
        ]
    )
    self.logger = logging.getLogger(__name__)

def setup_connections(self):
    """Setup database and GCP connections"""

    # MySQL connection
    try:
        self.db_connection = mysql.connector.connect(
            host=self.config['database']['host'],
            port=self.config['database']['port'],
            database=self.config['database']['database'],
            user=self.config['database']['username'],
            password=self.config['database']['password']
        )
        self.logger.info("Database connection established")
    except Exception as e:
        self.logger.error(f"Failed to connect to database: {e}")
        self.db_connection = None

    # GCS client
    try:
        self.storage_client = storage.Client(project=self.config['gcp']['project_id'])
        self.logger.info("GCS client initialized")
    except Exception as e:
        self.logger.error(f"Failed to initialize GCS client: {e}")
        self.storage_client = None

    # Security Command Center client
    try:
        self.scc_client = securitycenter.SecurityCenterClient()
        self.logger.info("Security Command Center client initialized")
    except Exception as e:
        self.logger.error(f"Failed to initialize SCC client: {e}")
        self.scc_client = None

def get_violations_summary(self, days=30):
    """Get violations summary from database"""

    if not self.db_connection:
        return None

    try:
        cursor = self.db_connection.cursor(dictionary=True)

        end_date = datetime.now()
        start_date = end_date - timedelta(days=days)

        # Get violations by rule
        cursor.execute("""
            SELECT 
                rule_name,
                violation_type,
                COUNT(*) as violation_count,
                COUNT(DISTINCT resource_id) as affected_resources
            FROM violations 
            WHERE created_at_datetime BETWEEN %s AND %s
            GROUP BY rule_name, violation_type
            ORDER BY violation_count DESC
        """, (start_date, end_date))

        violations_by_rule = cursor.fetchall()

        # Get violations by resource type
        cursor.execute("""
            SELECT 
                resource_type,
                COUNT(*) as violation_count,
                COUNT(DISTINCT resource_id) as affected_resources
            FROM violations 
            WHERE created_at_datetime BETWEEN %s AND %s
            GROUP BY resource_type
            ORDER BY violation_count DESC
        """, (start_date, end_date))

        violations_by_type = cursor.fetchall()

        # Get daily trend
        cursor.execute("""
            SELECT 
                DATE(created_at_datetime) as violation_date,
                COUNT(*) as violation_count
            FROM violations 
            WHERE created_at_datetime BETWEEN %s AND %s
            GROUP BY DATE(created_at_datetime)
            ORDER BY violation_date
        """, (start_date, end_date))

        daily_trend = cursor.fetchall()

        cursor.close()

        summary = {
            'period_days': days,
            'violations_by_rule': violations_by_rule,
            'violations_by_type': violations_by_type,
            'daily_trend': daily_trend,
            'total_violations': sum(v['violation_count'] for v in violations_by_rule),
            'generated_at': datetime.now().isoformat()
        }

        return summary

    except Exception as e:
        self.logger.error(f"Error getting violations summary: {e}")
        return None

def get_inventory_summary(self):
    """Get inventory summary from database"""

    if not self.db_connection:
        return None

    try:
        cursor = self.db_connection.cursor(dictionary=True)

        # Get latest inventory
        cursor.execute("""
            SELECT 
                inventory_type,
                COUNT(*) as resource_count
            FROM inventory i
            JOIN inventory_index ii ON i.inventory_index_id = ii.inventory_index_id
            WHERE ii.id = (SELECT MAX(id) FROM inventory_index WHERE completed_at_datetime IS NOT NULL)
            GROUP BY inventory_type
            ORDER BY resource_count DESC
        """)

        inventory_by_type = cursor.fetchall()

        # Get inventory history
        cursor.execute("""
            SELECT 
                completed_at_datetime,
                count_objects
            FROM inventory_index 
            WHERE completed_at_datetime IS NOT NULL
            ORDER BY completed_at_datetime DESC
            LIMIT 30
        """)

        inventory_history = cursor.fetchall()

        cursor.close()

        summary = {
            'inventory_by_type': inventory_by_type,
            'inventory_history': inventory_history,
            'total_resources': sum(i['resource_count'] for i in inventory_by_type),
            'generated_at': datetime.now().isoformat()
        }

        return summary

    except Exception as e:
        self.logger.error(f"Error getting inventory summary: {e}")
        return None

def get_compliance_score(self, violations_summary):
    """Calculate compliance score based on violations"""

    if not violations_summary:
        return 0

    total_violations = violations_summary['total_violations']

    # Weight violations by severity (based on rule name patterns)
    critical_weight = 10
    high_weight = 5
    medium_weight = 2
    low_weight = 1

    weighted_score = 0

    for violation in violations_summary['violations_by_rule']:
        rule_name = violation['rule_name'].lower()
        count = violation['violation_count']

        if any(keyword in rule_name for keyword in ['public', 'internet', 'all users', 'owner']):
            weighted_score += count * critical_weight
        elif any(keyword in rule_name for keyword in ['ssl', 'backup', 'encryption']):
            weighted_score += count * high_weight
        elif any(keyword in rule_name for keyword in ['logging', 'monitoring']):
            weighted_score += count * medium_weight
        else:
            weighted_score += count * low_weight

    # Calculate compliance score (0-100)
    max_possible_score = 1000  # Arbitrary baseline
    compliance_score = max(0, 100 - (weighted_score / max_possible_score * 100))

    return round(compliance_score, 2)

def generate_compliance_report(self, days=30):
    """Generate comprehensive compliance report"""

    violations_summary = self.get_violations_summary(days)
    inventory_summary = self.get_inventory_summary()

    if not violations_summary:
        self.logger.error("Failed to generate compliance report")
        return None

    compliance_score = self.get_compliance_score(violations_summary)

    report = {
        'report_metadata': {
            'generated_at': datetime.now().isoformat(),
            'period_days': days,
            'report_type': 'forseti_compliance'
        },
        'executive_summary': {
            'compliance_score': compliance_score,
            'total_violations': violations_summary['total_violations'],
            'total_resources': inventory_summary['total_resources'] if inventory_summary else 0,
            'period_days': days
        },
        'violations_summary': violations_summary,
        'inventory_summary': inventory_summary,
        'recommendations': self._generate_recommendations(violations_summary)
    }

    return report

def _generate_recommendations(self, violations_summary):
    """Generate recommendations based on violations"""

    recommendations = []

    if not violations_summary:
        return recommendations

    # Analyze top violations
    top_violations = sorted(
        violations_summary['violations_by_rule'], 
        key=lambda x: x['violation_count'], 
        reverse=True
    )[:5]

    for violation in top_violations:
        rule_name = violation['rule_name']
        count = violation['violation_count']

        if 'public' in rule_name.lower() or 'internet' in rule_name.lower():
            recommendations.append({
                'priority': 'HIGH',
                'title': 'Address Public Access Violations',
                'description': f"{count} resources have public access configured",
                'action': f"Review and restrict public access for {rule_name}",
                'rule_name': rule_name
            })

        elif 'firewall' in rule_name.lower():
            recommendations.append({
                'priority': 'HIGH',
                'title': 'Review Firewall Rules',
                'description': f"{count} firewall rule violations detected",
                'action': f"Audit and update firewall rules for {rule_name}",
                'rule_name': rule_name
            })

        elif 'iam' in rule_name.lower() or 'service account' in rule_name.lower():
            recommendations.append({
                'priority': 'MEDIUM',
                'title': 'Review IAM Permissions',
                'description': f"{count} IAM-related violations found",
                'action': f"Review and update IAM policies for {rule_name}",
                'rule_name': rule_name
            })

    return recommendations

def create_compliance_dashboard(self, report_data, output_file='forseti_dashboard.png'):
    """Create compliance dashboard visualization"""

    try:
        plt.style.use('seaborn-v0_8')
        fig, axes = plt.subplots(2, 3, figsize=(18, 12))

        violations_summary = report_data['violations_summary']
        inventory_summary = report_data['inventory_summary']
        executive_summary = report_data['executive_summary']

        # 1. Compliance Score Gauge
        compliance_score = executive_summary['compliance_score']
        colors = ['#e74c3c' if compliance_score < 70 else '#f39c12' if compliance_score < 85 else '#27ae60']

        axes[0, 0].pie([compliance_score, 100-compliance_score], 
                      labels=[f'{compliance_score}%', ''], 
                      colors=[colors[0], '#ecf0f1'],
                      startangle=90)
        axes[0, 0].set_title('Compliance Score')

        # 2. Violations by Rule (Top 10)
        if violations_summary['violations_by_rule']:
            top_rules = violations_summary['violations_by_rule'][:10]
            rule_names = [r['rule_name'][:30] + '...' if len(r['rule_name']) > 30 else r['rule_name'] 
                         for r in top_rules]
            violation_counts = [r['violation_count'] for r in top_rules]

            axes[0, 1].barh(rule_names, violation_counts, color='#e74c3c')
            axes[0, 1].set_title('Top 10 Violating Rules')
            axes[0, 1].set_xlabel('Violation Count')

        # 3. Violations by Resource Type
        if violations_summary['violations_by_type']:
            resource_types = [v['resource_type'] for v in violations_summary['violations_by_type']]
            type_counts = [v['violation_count'] for v in violations_summary['violations_by_type']]

            axes[0, 2].pie(type_counts, labels=resource_types, autopct='%1.1f%%')
            axes[0, 2].set_title('Violations by Resource Type')

        # 4. Daily Violation Trend
        if violations_summary['daily_trend']:
            dates = [datetime.strptime(str(d['violation_date']), '%Y-%m-%d') 
                    for d in violations_summary['daily_trend']]
            counts = [d['violation_count'] for d in violations_summary['daily_trend']]

            axes[1, 0].plot(dates, counts, marker='o', color='#e74c3c')
            axes[1, 0].set_title('Daily Violation Trend')
            axes[1, 0].set_ylabel('Violation Count')
            axes[1, 0].tick_params(axis='x', rotation=45)

        # 5. Inventory by Resource Type
        if inventory_summary and inventory_summary['inventory_by_type']:
            inv_types = [i['inventory_type'] for i in inventory_summary['inventory_by_type'][:8]]
            inv_counts = [i['resource_count'] for i in inventory_summary['inventory_by_type'][:8]]

            axes[1, 1].bar(inv_types, inv_counts, color='#3498db')
            axes[1, 1].set_title('Inventory by Resource Type')
            axes[1, 1].set_ylabel('Resource Count')
            axes[1, 1].tick_params(axis='x', rotation=45)

        # 6. Summary Metrics
        metrics_text = f"""
        Total Violations: {executive_summary['total_violations']}
        Total Resources: {executive_summary['total_resources']}
        Compliance Score: {executive_summary['compliance_score']}%

        Period: {executive_summary['period_days']} days
        Generated: {report_data['report_metadata']['generated_at'][:10]}
        """

        axes[1, 2].text(0.1, 0.5, metrics_text, fontsize=12, verticalalignment='center')
        axes[1, 2].set_xlim(0, 1)
        axes[1, 2].set_ylim(0, 1)
        axes[1, 2].axis('off')
        axes[1, 2].set_title('Summary Metrics')

        plt.tight_layout()
        plt.savefig(output_file, dpi=300, bbox_inches='tight')
        plt.close()

        self.logger.info(f"Compliance dashboard created: {output_file}")
        return output_file

    except Exception as e:
        self.logger.error(f"Error creating compliance dashboard: {e}")
        return None

def send_compliance_report(self, report_data, dashboard_file=None):
    """Send compliance report via email"""

    if not self.config.get('notifications', {}).get('email', {}).get('enabled', False):
        self.logger.info("Email notifications disabled")
        return False

    try:
        email_config = self.config['notifications']['email']

        # Create email message
        msg = MimeMultipart()
        msg['From'] = email_config['sender']
        msg['To'] = email_config['recipient']
        msg['Subject'] = f"Forseti Security Compliance Report - {datetime.now().strftime('%Y-%m-%d')}"

        # Create email body
        executive_summary = report_data['executive_summary']
        body = f"""
        Forseti Security Compliance Report

        Compliance Score: {executive_summary['compliance_score']}%
        Total Violations: {executive_summary['total_violations']}
        Total Resources: {executive_summary['total_resources']}
        Period: {executive_summary['period_days']} days

        Top Recommendations:
        """

        for rec in report_data['recommendations'][:5]:
            body += f"\n- {rec['title']}: {rec['description']}"

        body += f"\n\nGenerated at: {report_data['report_metadata']['generated_at']}"

        msg.attach(MimeText(body, 'plain'))

        # Attach dashboard if available
        if dashboard_file:
            with open(dashboard_file, 'rb') as attachment:
                part = MimeBase('application', 'octet-stream')
                part.set_payload(attachment.read())
                encoders.encode_base64(part)
                part.add_header(
                    'Content-Disposition',
                    f'attachment; filename= {dashboard_file}'
                )
                msg.attach(part)

        # Send email
        server = smtplib.SMTP(email_config['smtp_host'], email_config['smtp_port'])
        server.starttls()
        server.login(email_config['username'], email_config['password'])
        server.send_message(msg)
        server.quit()

        self.logger.info("Compliance report sent via email")
        return True

    except Exception as e:
        self.logger.error(f"Error sending compliance report: {e}")
        return False

def upload_to_gcs(self, report_data, bucket_name):
    """Upload report to Google Cloud Storage"""

    if not self.storage_client:
        return False

    try:
        bucket = self.storage_client.bucket(bucket_name)

        # Upload JSON report
        report_blob_name = f"forseti-reports/compliance-report-{datetime.now().strftime('%Y%m%d-%H%M%S')}.json"
        report_blob = bucket.blob(report_blob_name)
        report_blob.upload_from_string(json.dumps(report_data, indent=2))

        self.logger.info(f"Report uploaded to GCS: gs://{bucket_name}/{report_blob_name}")
        return True

    except Exception as e:
        self.logger.error(f"Error uploading to GCS: {e}")
        return False

def run_monitoring_workflow(self, days=30):
    """Run complete monitoring workflow"""

    self.logger.info("Starting Forseti Security monitoring workflow")

    # Generate report
    report = self.generate_compliance_report(days)
    if not report:
        self.logger.error("Failed to generate compliance report")
        return False

    # Save report to file
    report_file = f"forseti_compliance_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
    with open(report_file, 'w') as f:
        json.dump(report, f, indent=2)

    # Create dashboard
    dashboard_file = f"forseti_dashboard_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
    self.create_compliance_dashboard(report, dashboard_file)

    # Send report
    self.send_compliance_report(report, dashboard_file)

    # Upload to GCS
    if self.config.get('gcp', {}).get('bucket_name'):
        self.upload_to_gcs(report, self.config['gcp']['bucket_name'])

    self.logger.info("Forseti Security monitoring workflow completed")
    return True

def main(): """Main function for Forseti monitoring"""

import argparse
import yaml

parser = argparse.ArgumentParser(description='Forseti Security Monitor')
parser.add_argument('--config', default='forseti_monitor_config.yaml', help='Configuration file')
parser.add_argument('--days', type=int, default=30, help='Number of days to analyze')

args = parser.parse_args()

# Load configuration
try:
    with open(args.config, 'r') as f:
        config = yaml.safe_load(f)
except FileNotFoundError:
    # Create default configuration
    config = {
        'database': {
            'host': 'localhost',
            'port': 3306,
            'database': 'forseti_security',
            'username': 'forseti_security_user',
            'password': 'forseti123'
        },
        'gcp': {
            'project_id': 'your-project-id',
            'bucket_name': 'forseti-security-bucket'
        },
        'notifications': {
            'email': {
                'enabled': True,
                'smtp_host': 'smtp.gmail.com',
                'smtp_port': 587,
                'username': 'forseti@company.com',
                'password': 'app-password',
                'sender': 'forseti@company.com',
                'recipient': 'security-team@company.com'
            }
        }
    }

    with open(args.config, 'w') as f:
        yaml.dump(config, f, default_flow_style=False)

    print(f"Created default configuration: {args.config}")
    print("Please update the configuration file with your settings")
    return

# Run monitoring
monitor = ForsetiMonitor(config)
monitor.run_monitoring_workflow(args.days)

if name == "main": main() ```_

Automatisierung und Integration

CI/CD Integration

```yaml

.github/workflows/forseti-security-scan.yml

name: Forseti Security Scan

on: push: branches: [ main, develop ] pull_request: branches: [ main ] schedule: # Run daily at 2 AM UTC - cron: '0 2 * * *' workflow_dispatch: inputs: scan_type: description: 'Type of scan to run' required: false default: 'full' type: choice options: - full - inventory - scanner - explain

jobs: forseti-security-scan: runs-on: ubuntu-latest

steps:
- name: Checkout code
  uses: actions/checkout@v3

- name: Setup Python
  uses: actions/setup-python@v4
  with:
    python-version: '3.8'

- name: Install dependencies
  run: |
    pip install google-cloud-storage google-cloud-securitycenter mysql-connector-python pyyaml pandas matplotlib seaborn

- name: Setup Google Cloud credentials
  uses: google-github-actions/auth@v1
  with:
    credentials_json: ${{ secrets.GCP_SA_KEY }}

- name: Setup Google Cloud SDK
  uses: google-github-actions/setup-gcloud@v1

- name: Run Forseti Security scan
  env:
    FORSETI_SERVER_HOST: ${{ secrets.FORSETI_SERVER_HOST }}
    FORSETI_SERVER_PORT: ${{ secrets.FORSETI_SERVER_PORT }}
    FORSETI_DB_HOST: ${{ secrets.FORSETI_DB_HOST }}
    FORSETI_DB_PASSWORD: ${{ secrets.FORSETI_DB_PASSWORD }}
    GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
    GCP_ORGANIZATION_ID: ${{ secrets.GCP_ORGANIZATION_ID }}
  run: |
    # Create Forseti client configuration
    cat > forseti_client_config.yaml << EOF
    server_ip: ${FORSETI_SERVER_HOST}
    server_port: ${FORSETI_SERVER_PORT}
    EOF

    # Create monitoring configuration
    cat > forseti_monitor_config.yaml << EOF
    database:
      host: ${FORSETI_DB_HOST}
      port: 3306
      database: forseti_security
      username: forseti_security_user
      password: ${FORSETI_DB_PASSWORD}
    gcp:
      project_id: ${GCP_PROJECT_ID}
      organization_id: ${GCP_ORGANIZATION_ID}
      bucket_name: forseti-security-bucket
    notifications:
      email:
        enabled: false
    EOF

    # Install Forseti Security client
    git clone https: //github.com/forseti-security/forseti-security.git
    cd forseti-security
    git checkout v2.25.1
    pip install -r requirements.txt
    pip install -e .

    # Run Forseti operations based on scan type

| SCAN_TYPE="${{ github.event.inputs.scan_type | | 'full' }}" |

| if [ "$SCAN_TYPE" = "full" ] | | [ "$SCAN_TYPE" = "inventory" ]; then | echo "Running inventory scan..." python -m google.cloud.forseti.services.inventory.storage \ --config_file_path=../forseti_client_config.yaml fi

| if [ "$SCAN_TYPE" = "full" ] | | [ "$SCAN_TYPE" = "scanner" ]; then | echo "Running scanner..." python -m google.cloud.forseti.scanner.scanner \ --config_file_path=../forseti_client_config.yaml fi

| if [ "$SCAN_TYPE" = "full" ] | | [ "$SCAN_TYPE" = "explain" ]; then | echo "Running explain..." python -m google.cloud.forseti.services.explain.explain \ --config_file_path=../forseti_client_config.yaml fi

    # Generate compliance report
    cd ..
    python scripts/forseti_monitor.py \
      --config forseti_monitor_config.yaml \
      --days 7

- name: Evaluate security gate
  run: |
    python << 'EOF'
    import json
    import sys
    import glob

    # Find compliance report
    report_files = glob.glob('forseti_compliance_report_*.json')

    if not report_files:
        print("No compliance report found")
        sys.exit(0)

    with open(report_files[0], 'r') as f:
        report = json.load(f)

    executive_summary = report['executive_summary']
    compliance_score = executive_summary['compliance_score']
    total_violations = executive_summary['total_violations']

    print(f"Forseti Security Assessment Results: ")
    print(f"Compliance Score: {compliance_score}%")
    print(f"Total Violations: {total_violations}")

    # Security gate logic
    if compliance_score < 70:
        print("❌ SECURITY FAILURE!")
        print("Compliance score below acceptable threshold (70%)")
        sys.exit(1)

    if total_violations > 100:
        print("⚠️ WARNING: High number of violations!")
        sys.exit(1)

    print("✅ Security gate passed")
    EOF

- name: Upload scan results
  uses: actions/upload-artifact@v3
  with:
    name: forseti-security-results
    path: |
      forseti_compliance_report_*.json
      forseti_dashboard_*.png

- name: Comment PR with security status
  if: github.event_name == 'pull_request'
  uses: actions/github-script@v6
  with:
    script: |
      const fs = require('fs');
      const glob = require('glob');

      // Find compliance report
      const reportFiles = glob.sync('forseti_compliance_report_*.json');

      if (reportFiles.length === 0) {
        console.log('No compliance report found');
        return;
      }

      const report = JSON.parse(fs.readFileSync(reportFiles[0], 'utf8'));
      const summary = report.executive_summary;

      const comment = `## 🔒 Forseti Security Scan Results

      **Compliance Score: ** ${summary.compliance_score}%
      **Total Violations: ** ${summary.total_violations}
      **Total Resources: ** ${summary.total_resources}

      **Top Violations: **
      ${report.violations_summary.violations_by_rule.slice(0, 5).map(v => 
        `- ${v.rule_name}: ${v.violation_count} violations`
      ).join('\n')}

      **Recommendations: **
      ${report.recommendations.slice(0, 3).map(r => 
        `- **${r.title}**: ${r.description}`
      ).join('\n')}

      ${summary.compliance_score < 70 ? '⚠️ **Compliance score below threshold! Please review and remediate violations.**' : '✅ Security scan passed.'}

      [View detailed report](https: //github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})`;

      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: comment
      });

```_

Ressourcen und Dokumentation

Offizielle Mittel

GCP Sicherheitsressourcen

Compliance und Governance