From 1d385cf89f7f1c50d8d60b29ff7f518fd4d6fbb6 Mon Sep 17 00:00:00 2001 From: Riccardo Schirone <562321+ret2libc@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:31:57 +0200 Subject: [PATCH] Make deployment easier (#158) * deployment: just use the value in values.template * ci: disable integration tests and private settings * Download trailofbits cscope, not aixcc-finals one * ci: fix docker login to ghcr.io * Changes to allow non aixcc deployment * buttercup-ui: basic skeleton for a CRS interface * file-server implementation * add ui to k8s * other apis * try to fix k8s * remove some labels * fix ui * small fixes to doc * ui: support for cloning private repos * Add setup scripts for easy deployment * update scripts * update make/readme * small adj * address review * we need 0.0.0.0 for k8s --- Makefile | 135 ++++- QUICK_REFERENCE.md | 199 ++++++++ README.md | 342 ++++++++++--- deployment/env.template | 53 +- fuzzer/dockerfiles/runner_image.Dockerfile | 13 +- scripts/common.sh | 567 +++++++++++++++++++++ scripts/setup-local.sh | 65 +++ scripts/setup-production.sh | 177 +++++++ scripts/validate-setup.sh | 48 ++ 9 files changed, 1476 insertions(+), 123 deletions(-) create mode 100644 QUICK_REFERENCE.md create mode 100755 scripts/common.sh create mode 100755 scripts/setup-local.sh create mode 100755 scripts/setup-production.sh create mode 100755 scripts/validate-setup.sh diff --git a/Makefile b/Makefile index 3938a0da..af6ebb33 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,128 @@ -ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +# Makefile for Trail of Bits AIxCC Finals CRS -HOST_CRS_SCRATCH = $(ROOT_DIR)/crs_scratch -OSS_FUZZ_DIR = $(HOST_CRS_SCRATCH)/oss-fuzz +.PHONY: help setup-local setup-production validate deploy deploy-local deploy-production test clean -local-volumes: - mkdir -p $(HOST_CRS_SCRATCH) +# Default target +help: + @echo "Trail of Bits AIxCC Finals CRS - Available Commands:" + @echo "" + @echo "Setup:" + @echo " setup-local - Automated local development setup" + @echo " setup-production - Automated production AKS setup" + @echo " validate - Validate current setup and configuration" + @echo "" + @echo "Deployment:" + @echo " deploy - Deploy to current environment (local or production)" + @echo " deploy-local - Deploy to local Minikube environment" + @echo " deploy-production - Deploy to production AKS environment" + @echo "" + @echo "Testing:" + @echo " test - Run test task" + @echo "" + @echo "Development:" + @echo " lint - Lint all Python code" + @echo " lint-component - Lint specific component (e.g., make lint-component COMPONENT=orchestrator)" + @echo "" + @echo "Cleanup:" + @echo " clean - Clean up deployment" + @echo " clean-local - Clean up local environment" -oss-fuzz: - test -d $(OSS_FUZZ_DIR) || git clone https://github.com/google/oss-fuzz.git $(OSS_FUZZ_DIR) +# Setup targets +setup-local: + @echo "Setting up local development environment..." + ./scripts/setup-local.sh -up: local-volumes oss-fuzz - docker compose up -d $(services) +setup-production: + @echo "Setting up production AKS environment..." + ./scripts/setup-production.sh -demo: local-volumes oss-fuzz - TARGET_PACKAGE=nginx docker compose up -d $(services) +validate: + @echo "Validating setup..." + ./scripts/validate-setup.sh -down: - docker compose down --remove-orphans +# Deployment targets +deploy: + @echo "Deploying to current environment..." + cd deployment && make up + +wait-crs: + @echo "Waiting for CRS deployment to be ready..." + @if ! kubectl get namespace crs >/dev/null 2>&1; then \ + echo "Error: CRS namespace not found. Deploy first with 'make deploy'."; \ + exit 1; \ + fi + @while true; do \ + PENDING=$$(kubectl get pods -n crs --no-headers 2>/dev/null | grep -v 'Completed' | grep -v 'Running' | wc -l); \ + if [ "$$PENDING" -eq 0 ]; then \ + echo "All CRS pods are running."; \ + break; \ + else \ + echo "$$PENDING pods are not yet running. Waiting..."; \ + sleep 5; \ + fi \ + done + +crs-instance-id: + @echo "Getting CRS instance ID..." + @if ! kubectl get namespace crs >/dev/null 2>&1; then \ + echo "Error: CRS namespace not found. Deploy first with 'make deploy'."; \ + exit 1; \ + fi + echo "CRS instance ID: $$(kubectl get configmap -n crs crs-instance-id -o jsonpath='{.data.crs-instance-id}')" + +deploy-local: + @echo "Deploying to local Minikube environment..." + @if [ ! -f deployment/env ]; then \ + echo "Error: Configuration file not found. Run 'make setup-local' first."; \ + exit 1; \ + fi + cd deployment && make up + make crs-instance-id + make wait-crs + +deploy-production: + @echo "Deploying to production AKS environment..." + @if [ ! -f deployment/env ]; then \ + echo "Error: Configuration file not found. Run 'make setup-production' first."; \ + exit 1; \ + fi + cd deployment && make up + crs_instance_id=$$(make crs-instance-id) + echo "CRS instance ID: $$crs_instance_id" + make wait-crs + +# Testing targets +test: + @echo "Running test task..." + @if ! kubectl get namespace crs >/dev/null 2>&1; then \ + echo "Error: CRS namespace not found. Deploy first with 'make deploy'."; \ + exit 1; \ + fi + kubectl port-forward -n crs service/buttercup-ui 31323:1323 & + @sleep 3 + ./orchestrator/scripts/task_integration_test.sh + @pkill -f "kubectl port-forward" || true + +# Development targets +lint: + @echo "Linting all Python code..." + just lint-python-all + +lint-component: + @if [ -z "$(COMPONENT)" ]; then \ + echo "Error: COMPONENT not specified. Usage: make lint-component COMPONENT="; \ + echo "Available components: common, fuzzer, orchestrator, patcher, program-model, seed-gen"; \ + exit 1; \ + fi + @echo "Linting $(COMPONENT)..." + just lint-python $(COMPONENT) + +# Cleanup targets +clean: + @echo "Cleaning up deployment..." + cd deployment && make down + +clean-local: + @echo "Cleaning up local environment..." + minikube delete || true + rm -f deployment/env diff --git a/QUICK_REFERENCE.md b/QUICK_REFERENCE.md new file mode 100644 index 00000000..3149ab88 --- /dev/null +++ b/QUICK_REFERENCE.md @@ -0,0 +1,199 @@ +# Quick Reference Guide + +## Setup Commands + +### Local Development +```bash +# Automated setup +./scripts/setup-local.sh + +# Manual setup +cp deployment/env.template deployment/env +# Edit deployment/env with your API keys +cd deployment && make up +``` + +### Production AKS +```bash +# Automated setup +./scripts/setup-production.sh + +# Manual setup +az login --tenant aixcc.tech +# Create service principal and configure deployment/env +cd deployment && make up +``` + +## Common Commands + +### Kubernetes Management +```bash +# View all resources +kubectl get pods -A +kubectl get services -A +kubectl get ingress -A + +# View specific namespace +kubectl get pods -n crs +kubectl get services -n crs + +# Port forwarding +kubectl port-forward -n crs service/buttercup-competition-api 31323:1323 + +# View logs +kubectl logs -n crs +kubectl logs -n crs -l app=scheduler --tail=-1 --prefix + +# Debug pods +kubectl exec -it -n crs -- /bin/bash +``` + +### Testing +```bash +# Send test task +./orchestrator/scripts/task_crs.sh + +# Send SARIF message +./orchestrator/scripts/send_sarif.sh + +# Run unscored challenges +./orchestrator/scripts/challenge.sh +``` + +### Development +```bash +# Lint Python code +just lint-python-all +just lint-python + +# Docker development +docker-compose up -d +docker-compose --profile fuzzer-test up +``` + +### Minikube +```bash +# Start/stop +minikube start --driver=docker +minikube stop +minikube delete + +# Status +minikube status +minikube dashboard +``` + +### Azure AKS +```bash +# Get credentials +az aks get-credentials --name --resource-group + +# Scale cluster +# Update TF_VAR_usr_node_count in deployment/env +cd deployment && make up + +# View cluster info +az aks show --name --resource-group +``` + +## Configuration + +## Troubleshooting + +### Common Issues + +#### Minikube Issues +```bash +# Reset minikube +minikube delete +minikube start --driver=docker + +# Check status +minikube status +kubectl cluster-info +``` + +#### Docker Issues +```bash +# Permission issues +sudo usermod -aG docker $USER +# Log out and back in + +# Check Docker daemon +sudo systemctl status docker +sudo systemctl start docker +``` + +#### Helm Issues +```bash +# Update repositories +helm repo update +helm dependency update deployment/k8s/ + +# Check chart +helm lint deployment/k8s/ +``` + +#### Azure Issues +```bash +# Authentication +az login --tenant aixcc.tech +az account set --subscription + +# Check service principal +az ad sp list --display-name "ButtercupCRS*" +``` + +#### Kubernetes Issues +```bash +# Check cluster connectivity +kubectl cluster-info +kubectl get nodes + +# Check pods +kubectl describe pod -n crs +kubectl logs -n crs --previous + +# Check events +kubectl get events -n crs --sort-by='.lastTimestamp' +``` + +### Log Analysis + +#### Check Patch Submission +```bash +kubectl logs -n crs -l app=scheduler --tail=-1 --prefix | grep "WAIT_PATCH_PASS -> SUBMIT_BUNDLE" +``` + +#### Check Competition API +```bash +kubectl logs -n crs -l app=competition-api --tail=-1 --prefix +``` + +#### Check Fuzzer +```bash +kubectl logs -n crs -l app=fuzzer --tail=-1 --prefix +``` + +## File Locations + +### Configuration +- `deployment/env` - Main configuration file +- `deployment/env.template` - Configuration template +- `deployment/k8s/values-*.template` - Kubernetes value templates + +### Scripts +- `scripts/setup-local.sh` - Local development setup +- `scripts/setup-production.sh` - Production AKS setup +- `orchestrator/scripts/` - Testing and task scripts + +### Documentation +- `README.md` - Main documentation +- `deployment/README.md` - Detailed deployment guide + +## Support + +- Check logs: `kubectl logs -n crs ` +- View events: `kubectl get events -n crs` +- Debug pods: `kubectl exec -it -n crs -- /bin/bash` +- Monitor resources: `kubectl top pods -A` diff --git a/README.md b/README.md index 9ccca2fe..0c8473ea 100644 --- a/README.md +++ b/README.md @@ -1,143 +1,319 @@ -# Trail of Bits AIxCC Finals CRS +# Buttercup Cyber Reasoning System (CRS) -## Dependencies +**Buttercup** is a Cyber Reasoning System (CRS) developed by **Trail of Bits** for the **DARPA AIxCC (AI Cyber Challenge) competition**. It's a comprehensive automated vulnerability detection and patching system designed to compete in AI-driven cybersecurity challenges. + +## Quick Start Clone the repo with `--recurse-submodules` as some dependencies are submodules. -Follow the install instructions for the required dependencies: +Choose your deployment method: -* [Docker install guide](https://docs.docker.com/engine/install/ubuntu/) -* [kubectl install guide](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) -* [helm install guide](https://helm.sh/docs/intro/install/): -* [minikube install guide](https://minikube.sigs.k8s.io/docs/start/?arch=%2Flinux%2Fx86-64%2Fstable%2Fdebian+package) -* Git LFS for some tests +- **[Local Development](#local-development)** - Quick setup for development and testing +- **[Production AKS Deployment](#production-aks-deployment)** - Full production deployment on Azure Kubernetes Service -## Configuration +## Local Development -Create a new configuration file, starting from the default template: +The fastest way to get started with the **Buttercup CRS** system for development and testing. -```shell -cp \ - deployment/env.template \ - deployment/env +### Quick Setup (Recommended) + +Use our automated setup script: + +```bash +make setup-local ``` -Next, configure the following options. Follow the instructions in the comments when setting the `GHCR_AUTH` value. +This script will install all dependencies, configure the environment, and guide you through the setup process. -```shell -SCANTRON_GITHUB_PAT -GHCR_AUTH -OPENAI_API_KEY -ANTHROPIC_API_KEY -DOCKER_USERNAME -DOCKER_PAT +### Manual Setup + +If you prefer to set up manually, follow these steps: + +```bash +# Docker +curl -fsSL https://get.docker.com | sh +sudo usermod -aG docker $USER +# Log out and back in for group changes to take effect + +# kubectl +curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" +sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl + +# Helm +curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + +# Minikube +curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 +sudo install minikube-linux-amd64 /usr/local/bin/minikube + +# Git LFS (for some tests) +sudo apt-get install git-lfs +git lfs install ``` -### Settings specific to local development and testing +#### Manual Configuration -Use the hardcoded test credentials found in the comments: +1. **Create configuration file:** -```shell -AZURE_ENABLED=false -TAILSCALE_ENABLED=false -COMPETITION_API_KEY_ID: `11111111-1111-1111-1111-111111111111` -COMPETITION_API_KEY_TOKEN: `secret` -CRS_KEY_ID="515cc8a0-3019-4c9f-8c1c-72d0b54ae561" -CRS_KEY_TOKEN="VGuAC8axfOnFXKBB7irpNDOKcDjOlnyB" -CRS_API_HOSTNAME="" -BUTTERCUP_K8S_VALUES_TEMPLATE="k8s/values-minikube.template" -OTEL_ENDPOINT="" -OTEL_PROTOCOL="http" +```bash +cp deployment/env.template deployment/env ``` -Keep empty: +2. **Configure the environment file** (`deployment/env`): -```shell -AZURE_API_BASE="" -AZURE_API_KEY="" +Look at the comments in the `deployment/env.template` for how to set variables. + +### Start Local Development Environment + +1. **Start the services:** + +```bash +make deploy-local ``` -Commented out: +2. **Verify deployment:** -```shell -CRS_URL -CRS_API_HOSTNAME -LANGFUSE_HOST -LANGFUSE_PUBLIC_KEY -LANGFUSE_SECRET_KEY -OTEL_TOKEN +```bash +kubectl get pods -n crs +kubectl get services -n crs ``` -When [re-running unscored rounds](orchestrator/src/buttercup/orchestrator/mock_competition_api/README.md), set this to `true`: +3. **Submit the integration-test challenge to the CRS (for 30mins):** -```shell -MOCK_COMPETITION_API_ENABLED +```bash +make test ``` -## Authentication +**Alternative manual commands:** -### Docker +```bash +# Start services manually +cd deployment && make up -Log into ghcr.io: +# Port forward manually +kubectl port-forward -n crs service/buttercup-competition-api 31323:1323 -```shell -docker login ghcr.io -u +# Test manually +./orchestrator/scripts/task_integration_test.sh ``` -## Running the CRS +## Production AKS Deployment -### Starting the services +> **⚠️ Notice:** +> The following production deployment instructions have **not been fully tested**. +> Please proceed with caution and verify each step in your environment. +> If you encounter issues, consult the script comments and configuration files for troubleshooting. -```shell +Full production deployment of the **Buttercup CRS** on Azure Kubernetes Service with proper networking, monitoring, and scaling for the DARPA AIxCC competition. + +### Quick Setup (Recommended) + +Use our automated setup script: + +```bash +make setup-production +``` + +This script will check prerequisites, help create service principals, configure the environment, and validate your setup. + +#### Manual Setup + +If you prefer to set up manually, follow these steps: + +##### Prerequisites + +- Azure CLI installed and configured +- Terraform installed +- Active Azure subscription +- Access to competition Tailscale tailnet + +##### Azure Setup + +1. **Login to Azure:** + +```bash +az login --tenant aixcc.tech +``` + +2. **Create Service Principal:** + +```bash +# Get your subscription ID +az account show --query "{SubscriptionID:id}" --output table + +# Create service principal (replace with your subscription ID) +az ad sp create-for-rbac --name "ButtercupCRS" --role Contributor --scopes /subscriptions/ +``` + +##### Production Configuration + +1. **Configure environment file:** + +```bash +cp deployment/env.template deployment/env +``` + +2. **Update `deployment/env` for production:** + +Look at the comments in the `deployment/env.template` for how to set variables. +In particular, set `TF_VAR_*` variables, and `TAILSCALE_*` if used. + +### Deploy to AKS + +**Deploy the cluster and services:** + +```bash +make deploy-production +``` + +**Alternative manual command:** + +```bash cd deployment && make up ``` -### Stopping the services +### Scaling and Management -```shell +- **Scale nodes:** Update `TF_VAR_usr_node_count` in your env file and run `make up` +- **View logs:** `kubectl logs -n crs ` +- **Monitor resources:** `kubectl top pods -A` + +## Cleanup + +```bash +make clean +``` + +**Alternative manual command:** + +```bash cd deployment && make down ``` -### Sending the example-libpng task to the system +## Development Workflow -```shell -kubectl port-forward -n crs service/buttercup-competition-api 31323:1323 +### Using Makefile Shortcuts + +The **Buttercup CRS** project includes a Makefile with convenient shortcuts for common tasks: + +```bash +# View all available commands +make help + +# Setup +make setup-local # Automated local setup +make setup-production # Automated production setup +make validate # Validate current setup + +# Deployment +make deploy # Deploy to current environment +make deploy-local # Deploy to local Minikube +make deploy-production # Deploy to production AKS + +# Testing +make test # Run test task + +# Development +make lint # Lint all Python code +make lint-component COMPONENT=orchestrator # Lint specific component + +# Cleanup +make clean # Clean up deployment +make clean-local # Clean up local environment ``` -```shell -./orchestrator/scripts/task_crs.sh +### Running Tests + +```bash +# Lint all Python code +make lint + +# Lint specific component +make lint-component COMPONENT=orchestrator + +# Run test task +make test ``` -Send a SARIF message +**Alternative manual commands:** -```shell -./orchestrator/scripts/send_sarif.sh -``` +```bash +# Lint Python code +just lint-python-all -### Simulating Unscored Round 2 +# Run specific component tests +just lint-python orchestrator -```shell -kubectl port-forward -n crs service/buttercup-competition-api 31323:1323 -``` - -```shell +# Test manually +./orchestrator/scripts/task_upstream_libpng.sh ./orchestrator/scripts/challenge.sh ``` -Check that patches get submitted to the bundler. +### Docker Development -```shell -kubectl logs -n crs -l app=scheduler --tail=-1 --prefix | grep "WAIT_PATCH_PASS -> SUBMIT_BUNDLE" +```bash +# Build and run with Docker Compose (only for local development and quick testing) +docker-compose up -d ``` -If needing to debug, run the following to log into the pod. +### Kubernetes Development -```shell -kubectl get pods -n crs +```bash +# Port forward for local access +kubectl port-forward -n crs service/buttercup-competition-api 31323:1323 +# View logs +kubectl logs -n crs -l app=scheduler --tail=-1 --prefix + +# Debug pods kubectl exec -it -n crs -- /bin/bash ``` -## Run Unscored Challenges +## Troubleshooting -See [UNSCORED.md](UNSCORED.md) +### Common Issues + +1. **Minikube won't start:** + +```bash +minikube delete +``` + +2. **Docker permission issues:** + +```bash +sudo usermod -aG docker $USER +# Log out and back in +``` + +3. **Helm chart issues:** + +```bash +helm repo update +helm dependency update deployment/k8s/ +``` + +4. **Azure authentication:** + +```bash +az login --tenant aixcc.tech +az account set --subscription +``` + +### Getting Help + +- **Validate your setup:** `make validate` - Check if your environment is ready +- Check the [Quick Reference Guide](QUICK_REFERENCE.md) for common commands and troubleshooting +- Check the [deployment README](deployment/README.md) for detailed deployment information +- Check logs: `kubectl logs -n crs ` + +## Architecture + +The **Buttercup CRS** system consists of several components designed to work together for automated vulnerability detection and patching: + +- **Orchestrator**: Coordinates the overall repair process and manages the workflow +- **Fuzzer**: Discovers vulnerabilities through intelligent fuzzing techniques +- **Patcher**: Generates and applies security patches to fix vulnerabilities +- **Program Model**: Analyzes code structure and semantics for better understanding +- **Seed Generator**: Creates targeted test cases for vulnerability discovery +- **Competition API**: Interfaces with the DARPA AIxCC competition platform diff --git a/deployment/env.template b/deployment/env.template index aa373f52..fb44ce6c 100644 --- a/deployment/env.template +++ b/deployment/env.template @@ -1,7 +1,7 @@ # Reference a values file for kubernetes deployment. This should be a template # file, filled by crs-architecture.sh with the correct variables. # See values-upstream-minikube.template, values-minikube.template, values-aks.template, values-prod.template -export BUTTERCUP_K8S_VALUES_TEMPLATE="k8s/values-minikube.template" +export BUTTERCUP_K8S_VALUES_TEMPLATE="k8s/values-upstream-minikube.template" # Namespace used to install the whole CRS in. export BUTTERCUP_NAMESPACE=crs @@ -16,29 +16,29 @@ export CLUSTER_TYPE=minikube # or "aks" # These are terraform variables, necessary only for actual deployment in AKS # See README.md for instructions on how to set them up. -export TF_VAR_ARM_CLIENT_ID="" -export TF_VAR_ARM_CLIENT_SECRET="" -export TF_VAR_ARM_TENANT_ID="" -export TF_VAR_ARM_SUBSCRIPTION_ID="" -export TF_VAR_usr_node_count=50 -export TF_VAR_resource_group_name_prefix="" +# export TF_VAR_ARM_CLIENT_ID="" +# export TF_VAR_ARM_CLIENT_SECRET="" +# export TF_VAR_ARM_TENANT_ID="" +# export TF_VAR_ARM_SUBSCRIPTION_ID="" +# export TF_VAR_usr_node_count=50 +# export TF_VAR_resource_group_name_prefix="" # TailScale variables, necessary only for production/staging deployments export TAILSCALE_ENABLED=false # or true -export TS_CLIENT_ID="" -export TS_CLIENT_SECRET="" -export TS_OP_TAG="" +# export TS_CLIENT_ID="" +# export TS_CLIENT_SECRET="" +# export TS_OP_TAG="" -# Competition API settings, used to properly connect to the right endpoint and +# AIxCC - Competition API settings, used to properly connect to the right endpoint and # with the right authentication. If COMPETITION_API_ENABLED is true, a test API # will be deployed and configured according to the variables. # SCANTRON_GITHUB_PAT is a GitHub PAT with at least package:read and repo:write # permissions. -export COMPETITION_API_ENABLED=true # or false -export COMPETITION_API_KEY_ID="" # 11111111-1111-1111-1111-111111111111 -export COMPETITION_API_KEY_TOKEN="" # secret +# export COMPETITION_API_ENABLED=false # or true +# export COMPETITION_API_KEY_ID="11111111-1111-1111-1111-111111111111" +# export COMPETITION_API_KEY_TOKEN="secret" # export COMPETITION_API_URL="" -export SCANTRON_GITHUB_PAT="" +# export SCANTRON_GITHUB_PAT="" # Start an additional pod for running challenges from blobs and in the same times and using same ids # as in the organized round. See the orchestrator/src/buttercup/orchestrator/mock_competition_api/README.md @@ -46,9 +46,9 @@ export SCANTRON_GITHUB_PAT="" export MOCK_COMPETITION_API_ENABLED=false # or true # CRS settings -export CRS_KEY_ID="" # 515cc8a0-3019-4c9f-8c1c-72d0b54ae561 -export CRS_KEY_TOKEN="" # VGuAC8axfOnFXKBB7irpNDOKcDjOlnyB -export CRS_KEY_TOKEN_HASH='' # $argon2id$v=19$m=65536,t=3,p=4$Dg1v6NPGTyXPoOPF4ozD5A$wa/85ttk17bBsIASSwdR/uGz5UKN/bZuu4wu+JIy1iA +export CRS_KEY_ID="515cc8a0-3019-4c9f-8c1c-72d0b54ae561" +export CRS_KEY_TOKEN="VGuAC8axfOnFXKBB7irpNDOKcDjOlnyB" +export CRS_KEY_TOKEN_HASH='$argon2id$v=19$m=65536,t=3,p=4$Dg1v6NPGTyXPoOPF4ozD5A$wa/85ttk17bBsIASSwdR/uGz5UKN/bZuu4wu+JIy1iA' # export CRS_URL="" # export CRS_API_HOSTNAME="" @@ -58,9 +58,9 @@ export CRS_KEY_TOKEN_HASH='' # $argon2id$v=19$m=6 export GHCR_AUTH="" # LiteLLM/LLMs settings -export LITELLM_MASTER_KEY="" # Generate with: openssl rand -hex 16 -export AZURE_API_BASE="" -export AZURE_API_KEY="" +export LITELLM_MASTER_KEY="d5179c62ae1c7366e3ee09775d0993d5" # Generate with: openssl rand -hex 16 +export AZURE_API_BASE="" +export AZURE_API_KEY="" export OPENAI_API_KEY="" export ANTHROPIC_API_KEY="" @@ -73,16 +73,17 @@ export ANTHROPIC_API_KEY="" # OpenTelemetry endpoint settings (e.g. SigNoz) # export OTEL_ENDPOINT="" # export OTEL_TOKEN="" +# export OTEL_PROTOCOL=grpc # Docker Hub credentials for doing logged requests while getting Container -# Images from DockerHub. -export DOCKER_USERNAME="" -export DOCKER_PAT="" +# Images from DockerHub. If not set, the system will perform unauthenticated requests. +# export DOCKER_USERNAME="" +# export DOCKER_PAT="" # Optionally modify the container image org part used for accessing challenges # containers. Use aixcc-afc by default, but modify this to use upstream oss-fuzz. -# export FUZZ_TOOLING_CONTAINER_ORG="gcr.io/oss-fuzz" +export FUZZ_TOOLING_CONTAINER_ORG="gcr.io/oss-fuzz" # Docker build arguments, useful for local deployment # By default these points to the aixcc-finals images -# export FUZZER_BASE_IMAGE="gcr.io/oss-fuzz-base/base-runner" +export FUZZER_BASE_IMAGE="gcr.io/oss-fuzz-base/base-runner" diff --git a/fuzzer/dockerfiles/runner_image.Dockerfile b/fuzzer/dockerfiles/runner_image.Dockerfile index 488fcb90..b2fe9da1 100644 --- a/fuzzer/dockerfiles/runner_image.Dockerfile +++ b/fuzzer/dockerfiles/runner_image.Dockerfile @@ -13,7 +13,18 @@ RUN uv python install python3.10 FROM base-image AS runner-base RUN apt-get update # TODO(Ian): maybe we should have a different base image for the builder -RUN curl -fsSL https://get.docker.com | sh +RUN apt-get install ca-certificates curl +RUN install -m 0755 -d /etc/apt/keyrings +RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc +RUN chmod a+r /etc/apt/keyrings/docker.asc + +# Add the repository to Apt sources: +RUN echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null +RUN apt-get update +RUN apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin FROM base-image AS builder diff --git a/scripts/common.sh b/scripts/common.sh new file mode 100755 index 00000000..63a7d5aa --- /dev/null +++ b/scripts/common.sh @@ -0,0 +1,567 @@ +#!/bin/bash + +# Common functions and variables for Buttercup CRS setup scripts +# This script should be sourced by other setup scripts + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Function to check if running as root +check_not_root() { + if [[ $EUID -eq 0 ]]; then + print_error "This script should not be run as root" + exit 1 + fi +} + +# Function to install Docker +install_docker() { + print_status "Installing Docker..." + if ! command_exists docker; then + curl -fsSL https://get.docker.com | sh + print_status "Adding user to Docker group (sudo required)..." + sudo usermod -aG docker $USER + print_success "Docker installed successfully" + print_warning "You need to log out and back in for Docker group changes to take effect" + else + print_success "Docker is already installed" + fi +} + +# Function to install kubectl +install_kubectl() { + print_status "Installing kubectl..." + if ! command_exists kubectl; then + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl + rm kubectl + print_success "kubectl installed successfully" + else + print_success "kubectl is already installed" + fi +} + +# Function to install Helm +install_helm() { + print_status "Installing Helm..." + if ! command_exists helm; then + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 + chmod 700 get_helm.sh + ./get_helm.sh + rm get_helm.sh + print_success "Helm installed successfully" + else + print_success "Helm is already installed" + fi +} + +# Function to install Minikube +install_minikube() { + print_status "Installing Minikube..." + if ! command_exists minikube; then + curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64 + sudo install minikube-linux-amd64 /usr/local/bin/minikube + rm minikube-linux-amd64 + print_success "Minikube installed successfully" + else + print_success "Minikube is already installed" + fi +} + +# Function to install Git LFS +install_git_lfs() { + print_status "Installing Git LFS..." + if ! command_exists git-lfs; then + sudo apt-get update + sudo apt-get install -y git-lfs + git lfs install + print_success "Git LFS installed successfully" + else + print_success "Git LFS is already installed" + fi +} + +# Function to install Just +install_just() { + print_status "Installing Just..." + if ! command_exists just; then + if command_exists curl; then + # Install using the official installer + curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash + elif command_exists apt-get; then + sudo apt-get update + sudo apt-get install -y just + elif command_exists yum; then + sudo yum install -y just + elif command_exists brew; then + brew install just + else + print_error "Could not install Just. Please install it manually." + return 1 + fi + print_success "Just installed successfully" + else + print_success "Just is already installed" + fi +} + +# Function to check Docker +check_docker() { + print_status "Checking Docker..." + if command_exists docker; then + if docker info >/dev/null 2>&1; then + print_success "Docker is running" + else + print_error "Docker is installed but not running" + return 1 + fi + else + print_error "Docker is not installed" + return 1 + fi +} + +# Function to check kubectl +check_kubectl() { + print_status "Checking kubectl..." + if command_exists kubectl; then + print_success "kubectl is installed" + else + print_error "kubectl is not installed" + return 1 + fi +} + +# Function to check Helm +check_helm() { + print_status "Checking Helm..." + if command_exists helm; then + print_success "Helm is installed" + else + print_error "Helm is not installed" + return 1 + fi +} + +# Function to check Minikube +check_minikube() { + print_status "Checking Minikube..." + if command_exists minikube; then + if minikube status >/dev/null 2>&1; then + print_success "Minikube is running" + else + print_warning "Minikube is installed but not running" + fi + else + print_warning "Minikube is not installed (only needed for local development)" + fi +} + +# Function to check Azure CLI +check_azure_cli() { + print_status "Checking Azure CLI..." + if command_exists az; then + if az account show >/dev/null 2>&1; then + local subscription=$(az account show --query name -o tsv) + print_success "Azure CLI is logged in (subscription: $subscription)" + else + print_warning "Azure CLI is installed but not logged in" + fi + else + print_warning "Azure CLI is not installed (only needed for AKS deployment)" + fi +} + +# Function to check Terraform +check_terraform() { + print_status "Checking Terraform..." + if command_exists terraform; then + print_success "Terraform is installed" + else + print_warning "Terraform is not installed (only needed for AKS deployment)" + fi +} + +# Function to check Just +check_just() { + print_status "Checking Just..." + if command_exists just; then + print_success "Just is installed" + else + print_error "Just is not installed" + return 1 + fi +} + +# Function to setup configuration file +setup_config_file() { + local overwrite_existing=${1:-false} + + print_status "Setting up configuration..." + + if [ ! -f "deployment/env" ]; then + cp deployment/env.template deployment/env + print_success "Configuration file created from template" + else + print_warning "Configuration file already exists" + if [ "$overwrite_existing" = "true" ]; then + read -p "Do you want to overwrite it? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + cp deployment/env.template deployment/env + print_success "Configuration file overwritten" + fi + fi + fi +} + +# Function to configure LangFuse +configure_langfuse() { + print_status "Configuring LangFuse (optional monitoring)..." + + # Source the env file to check current values + if [ -f "deployment/env" ]; then + source deployment/env + fi + + # Check if LangFuse is already enabled + if [ "$LANGFUSE_ENABLED" = "true" ] && [ -n "$LANGFUSE_HOST" ] && [ -n "$LANGFUSE_PUBLIC_KEY" ]; then + print_status "LangFuse is already configured:" + echo " Host: $LANGFUSE_HOST" + echo " Public Key: $LANGFUSE_PUBLIC_KEY" + read -p "Do you want to reconfigure LangFuse? (y/n): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "Keeping existing LangFuse configuration" + return + fi + fi + + read -p "Do you want to enable LangFuse for LLM monitoring? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_status "LangFuse configuration:" + read -p "Enter LangFuse host URL: " langfuse_host + read -p "Enter LangFuse public key: " langfuse_public_key + read -s -p "Enter LangFuse secret key: " langfuse_secret_key + echo + + # Update the env file + sed -i "s|.*export LANGFUSE_ENABLED=.*|export LANGFUSE_ENABLED=true|" deployment/env + sed -i "s|.*export LANGFUSE_HOST=.*|export LANGFUSE_HOST=\"$langfuse_host\"|" deployment/env + sed -i "s|.*export LANGFUSE_PUBLIC_KEY=.*|export LANGFUSE_PUBLIC_KEY=\"$langfuse_public_key\"|" deployment/env + sed -i "s|.*export LANGFUSE_SECRET_KEY=.*|export LANGFUSE_SECRET_KEY=\"$langfuse_secret_key\"|" deployment/env + + print_success "LangFuse configured successfully" + else + print_status "LangFuse disabled" + sed -i "s|.*export LANGFUSE_ENABLED=.*|export LANGFUSE_ENABLED=false|" deployment/env + fi +} + +# Function to configure required API keys for local development +configure_local_api_keys() { + print_status "Configuring required API keys for local development..." + + # Source the env file to check current values + if [ -f "deployment/env" ]; then + source deployment/env + fi + + # OpenAI API Key + if [ -n "$OPENAI_API_KEY" ] && [ "$OPENAI_API_KEY" != "" ]; then + print_status "OpenAI API key is already configured" + else + read -s -p "Enter your OpenAI API key: " openai_key + echo + sed -i "s|.*export OPENAI_API_KEY=.*|export OPENAI_API_KEY=\"$openai_key\"|" deployment/env + fi + + # Anthropic API Key + if [ -n "$ANTHROPIC_API_KEY" ] && [ "$ANTHROPIC_API_KEY" != "" ]; then + print_status "Anthropic API key is already configured" + else + read -s -p "Enter your Anthropic API key: " anthropic_key + echo + sed -i "s|.*export ANTHROPIC_API_KEY=.*|export ANTHROPIC_API_KEY=\"$anthropic_key\"|" deployment/env + fi + + # GitHub Container Registry + if [ -n "$GHCR_AUTH" ] && [ "$GHCR_AUTH" != "" ]; then + print_status "GitHub Container Registry authentication is already configured" + else + read -p "Enter your GitHub username (press Enter to use 'USERNAME'): " ghcr_username + if [ -z "$ghcr_username" ]; then + ghcr_username="USERNAME" + fi + read -s -p "Enter your GitHub Personal Access Token (PAT): " ghcr_pat + echo + + # Compute GHCR_AUTH + ghcr_auth=$(echo -n "$ghcr_username:$ghcr_pat" | base64) + sed -i "s|.*export GHCR_AUTH=.*|export GHCR_AUTH=\"$ghcr_auth\"|" deployment/env + fi + + # Docker Hub credentials (optional) + if [ -n "$DOCKER_USERNAME" ] && [ "$DOCKER_USERNAME" != "" ]; then + print_status "Docker Hub credentials are already configured (username: $DOCKER_USERNAME)" + else + read -p "Enter your Docker Hub username (optional, press Enter to skip): " docker_username + if [ -n "$docker_username" ]; then + read -s -p "Enter your Docker Hub Personal Access Token: " docker_pat + echo + + # Set Docker credentials (handles both commented and uncommented lines) + sed -i "s|.*export DOCKER_USERNAME=.*|export DOCKER_USERNAME=\"$docker_username\"|" deployment/env + sed -i "s|.*export DOCKER_PAT=.*|export DOCKER_PAT=\"$docker_pat\"|" deployment/env + fi + fi + + print_success "API keys configured successfully" +} + + + +# Function to configure OTEL telemetry +configure_otel() { + print_status "Configuring OpenTelemetry telemetry (optional)..." + + # Source the env file to check current values + if [ -f "deployment/env" ]; then + source deployment/env + fi + + # Check if OTEL is already configured + if [ -n "$OTEL_ENDPOINT" ] && [ "$OTEL_ENDPOINT" != "" ] && [ "$OTEL_ENDPOINT" != "" ]; then + print_status "OpenTelemetry is already configured:" + echo " Endpoint: $OTEL_ENDPOINT" + echo " Protocol: $OTEL_PROTOCOL" + read -p "Do you want to reconfigure OpenTelemetry? (y/n): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "Keeping existing OpenTelemetry configuration" + return + fi + fi + + read -p "Do you want to enable OpenTelemetry telemetry? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_status "OpenTelemetry configuration:" + read -p "Enter OTEL endpoint URL: " otel_endpoint + read -p "Enter OTEL protocol (http/grpc): " otel_protocol + read -s -p "Enter OTEL token (optional, press Enter to skip): " otel_token + echo + + # Update the env file + sed -i "s|.*export OTEL_ENDPOINT=.*|export OTEL_ENDPOINT=\"$otel_endpoint\"|" deployment/env + sed -i "s|.*export OTEL_PROTOCOL=.*|export OTEL_PROTOCOL=\"$otel_protocol\"|" deployment/env + + if [ -n "$otel_token" ]; then + sed -i "s|.*export OTEL_TOKEN=.*|export OTEL_TOKEN=\"$otel_token\"|" deployment/env + fi + + print_success "OpenTelemetry configured successfully" + else + print_status "OpenTelemetry disabled" + sed -i "s|.*export OTEL_ENDPOINT=.*|# export OTEL_ENDPOINT=\"\"|" deployment/env + sed -i "s|.*export OTEL_PROTOCOL=.*|# export OTEL_PROTOCOL=\"http\"|" deployment/env + sed -i "s|.*export OTEL_TOKEN=.*|# export OTEL_TOKEN=\"\"|" deployment/env + fi +} + +# Function to check configuration file +check_config() { + print_status "Checking configuration file..." + if [ ! -f "deployment/env" ]; then + print_error "Configuration file deployment/env does not exist" + print_status "Run: cp deployment/env.template deployment/env" + return 1 + fi + + print_success "Configuration file exists" + + # Source the env file to check variables + source deployment/env + + # Check cluster type + if [ -n "$CLUSTER_TYPE" ]; then + print_success "CLUSTER_TYPE is set to: $CLUSTER_TYPE" + else + print_error "CLUSTER_TYPE is not set" + return 1 + fi + + # Check template + if [ -n "$BUTTERCUP_K8S_VALUES_TEMPLATE" ]; then + print_success "BUTTERCUP_K8S_VALUES_TEMPLATE is set to: $BUTTERCUP_K8S_VALUES_TEMPLATE" + else + print_error "BUTTERCUP_K8S_VALUES_TEMPLATE is not set" + return 1 + fi +} + +# Function to check Minikube configuration +check_minikube_config() { + print_status "Checking Minikube configuration..." + + local errors=0 + + # Check required API keys + local required_vars=( + "OPENAI_API_KEY" + "ANTHROPIC_API_KEY" + "GHCR_AUTH" + ) + + for var in "${required_vars[@]}"; do + if [ -z "${!var}" ] || [ "${!var}" = "" ]; then + print_error "Required variable $var is not set or has placeholder value" + errors=$((errors + 1)) + fi + done + + # Check optional LangFuse configuration + if [ "$LANGFUSE_ENABLED" = "true" ]; then + local langfuse_vars=( + "LANGFUSE_HOST" + "LANGFUSE_PUBLIC_KEY" + "LANGFUSE_SECRET_KEY" + ) + + for var in "${langfuse_vars[@]}"; do + if [ -z "${!var}" ] || [ "${!var}" = "" ]; then + print_error "LangFuse variable $var is not set or has placeholder value" + errors=$((errors + 1)) + fi + done + fi + + # Check optional OTEL configuration + if [ -n "$OTEL_ENDPOINT" ] && [ "$OTEL_ENDPOINT" != "" ]; then + if [ -z "$OTEL_PROTOCOL" ] || [ "$OTEL_PROTOCOL" = "" ]; then + print_error "OTEL_PROTOCOL is not set when OTEL_ENDPOINT is configured" + errors=$((errors + 1)) + fi + fi + + if [ $errors -eq 0 ]; then + print_success "Minikube configuration is valid" + else + print_error "Minikube configuration has $errors error(s)" + return $errors + fi +} + +# Function to check AKS configuration +check_aks_config() { + print_status "Checking AKS configuration..." + + local errors=0 + + # Check Terraform variables + local terraform_vars=( + "TF_VAR_ARM_CLIENT_ID" + "TF_VAR_ARM_CLIENT_SECRET" + "TF_VAR_ARM_TENANT_ID" + "TF_VAR_ARM_SUBSCRIPTION_ID" + ) + + for var in "${terraform_vars[@]}"; do + if [ -z "${!var}" ] || [ "${!var}" = "" ]; then + print_error "Required Terraform variable $var is not set or has placeholder value" + errors=$((errors + 1)) + fi + done + + # Check API keys + local api_vars=( + "OPENAI_API_KEY" + "ANTHROPIC_API_KEY" + "GHCR_AUTH" + "CRS_KEY_ID" + "CRS_KEY_TOKEN" + "COMPETITION_API_KEY_ID" + "COMPETITION_API_KEY_TOKEN" + ) + + for var in "${api_vars[@]}"; do + if [ -z "${!var}" ] || [ "${!var}" = "" ]; then + print_error "Required API variable $var is not set or has placeholder value" + errors=$((errors + 1)) + fi + done + + # Check Tailscale (optional but recommended) + if [ "$TAILSCALE_ENABLED" = "true" ]; then + local tailscale_vars=( + "TS_CLIENT_ID" + "TS_CLIENT_SECRET" + "TS_OP_TAG" + ) + + for var in "${tailscale_vars[@]}"; do + if [ -z "${!var}" ] || [ "${!var}" = "" ]; then + print_error "Tailscale variable $var is not set or has placeholder value" + errors=$((errors + 1)) + fi + done + fi + + # Check optional LangFuse configuration + if [ "$LANGFUSE_ENABLED" = "true" ]; then + local langfuse_vars=( + "LANGFUSE_HOST" + "LANGFUSE_PUBLIC_KEY" + "LANGFUSE_SECRET_KEY" + ) + + for var in "${langfuse_vars[@]}"; do + if [ -z "${!var}" ] || [ "${!var}" = "" ]; then + print_error "LangFuse variable $var is not set or has placeholder value" + errors=$((errors + 1)) + fi + done + fi + + # Check optional OTEL configuration + if [ -n "$OTEL_ENDPOINT" ] && [ "$OTEL_ENDPOINT" != "" ]; then + if [ -z "$OTEL_PROTOCOL" ] || [ "$OTEL_PROTOCOL" = "" ]; then + print_error "OTEL_PROTOCOL is not set when OTEL_ENDPOINT is configured" + errors=$((errors + 1)) + fi + fi + + if [ $errors -eq 0 ]; then + print_success "AKS configuration is valid" + else + print_error "AKS configuration has $errors error(s)" + return $errors + fi +} diff --git a/scripts/setup-local.sh b/scripts/setup-local.sh new file mode 100755 index 00000000..6dc79624 --- /dev/null +++ b/scripts/setup-local.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# Local Development Setup Script for Buttercup CRS +# This script automates the setup process for local development + +set -e + +# Source common functions +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +echo "🚀 Setting up Buttercup CRS for local development..." + +# Check if running as root +check_not_root + +# Function to setup configuration +setup_config() { + setup_config_file + + # Configure required API keys + configure_local_api_keys + + # Configure LangFuse (optional) + configure_langfuse + + # Configure OTEL telemetry (optional) + configure_otel +} + +# Function to verify setup +verify_setup() { + print_status "Verifying setup..." + + # Use the main Makefile validation target + if make validate >/dev/null 2>&1; then + print_success "Setup verification completed successfully!" + print_status "Next steps:" + echo " 1. Run: make deploy-local" + echo " 2. Test with: make test" + else + print_error "Setup verification failed. Run 'make validate' for details." + exit 1 + fi +} + +# Main execution +main() { + print_status "Starting local development setup..." + + install_docker + install_kubectl + install_helm + install_minikube + install_git_lfs + install_just + setup_config + + verify_setup + + print_success "Local development setup completed!" +} + +# Run main function +main "$@" diff --git a/scripts/setup-production.sh b/scripts/setup-production.sh new file mode 100755 index 00000000..e051216c --- /dev/null +++ b/scripts/setup-production.sh @@ -0,0 +1,177 @@ +#!/bin/bash + +# Production AKS Deployment Setup Script for Buttercup CRS +# This script helps configure and validate production deployment settings + +set -e + +# Source common functions +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +echo "🏭 Setting up Buttercup CRS for production AKS deployment..." + +# Check if running as root +check_not_root + +# Function to setup service principal +setup_service_principal() { + print_status "Setting up Azure Service Principal..." + + # Get current subscription + local subscription_id=$(az account show --query id -o tsv) + local subscription_name=$(az account show --query name -o tsv) + + print_status "Current subscription: $subscription_name ($subscription_id)" + + read -p "Do you want to create a new service principal? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + local sp_name="ButtercupCRS-$(date +%Y%m%d-%H%M%S)" + print_status "Creating service principal: $sp_name" + + local sp_output=$(az ad sp create-for-rbac --name "$sp_name" --role Contributor --scopes "/subscriptions/$subscription_id" --output json) + + local app_id=$(echo "$sp_output" | jq -r '.appId') + local password=$(echo "$sp_output" | jq -r '.password') + local tenant_id=$(echo "$sp_output" | jq -r '.tenant') + + print_success "Service principal created successfully" + echo + print_status "Service Principal Details:" + echo " Name: $sp_name" + echo " App ID: $app_id" + echo " Tenant ID: $tenant_id" + echo " Password: $password" + echo + print_warning "Save these credentials securely!" + echo + + # Export environment variables + export TF_ARM_TENANT_ID="$tenant_id" + export TF_ARM_CLIENT_ID="$app_id" + export TF_ARM_CLIENT_SECRET="$password" + export TF_ARM_SUBSCRIPTION_ID="$subscription_id" + + print_status "Environment variables exported for current session" + else + print_status "Using existing service principal" + print_status "Please set the following environment variables:" + echo " export TF_ARM_TENANT_ID=\"\"" + echo " export TF_ARM_CLIENT_ID=\"\"" + echo " export TF_ARM_CLIENT_SECRET=\"\"" + echo " export TF_ARM_SUBSCRIPTION_ID=\"\"" + fi +} + +# Function to setup configuration +setup_config() { + print_status "Setting up production configuration..." + + setup_config_file "true" + + # Configure required API keys + configure_local_api_keys + + # Configure LangFuse (optional) + configure_langfuse + + # Configure OTEL telemetry (optional) + configure_otel +} + +# Function to validate configuration +validate_config() { + print_status "Validating configuration..." + + # Use the main Makefile validation target + if make validate >/dev/null 2>&1; then + print_success "Configuration validation passed!" + else + print_error "Configuration validation failed. Run 'make validate' for details." + return 1 + fi +} + +# Function to setup remote state (optional) +setup_remote_state() { + print_status "Setting up Terraform remote state..." + + read -p "Do you want to configure remote state storage? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_status "This will create Azure resources for remote state storage" + + # Get resource group name + read -p "Enter resource group name for state storage (e.g., buttercup-tfstate-rg): " state_rg + read -p "Enter storage account name (e.g., buttercuptfstate): " storage_account + + # Create resource group + print_status "Creating resource group: $state_rg" + az group create --name "$state_rg" --location eastus + + # Create storage account + print_status "Creating storage account: $storage_account" + az storage account create --resource-group "$state_rg" --name "$storage_account" --sku Standard_LRS --encryption-services blob + + # Create container + print_status "Creating storage container" + az storage container create --name tfstate --account-name "$storage_account" --auth-mode login + + # Update backend.tf + print_status "Updating backend.tf" + cat > deployment/backend.tf << EOF +terraform { + backend "azurerm" { + resource_group_name = "$state_rg" + storage_account_name = "$storage_account" + container_name = "tfstate" + key = "terraform.tfstate" + } +} +EOF + + print_success "Remote state storage configured" + else + print_status "Skipping remote state setup (using local state)" + fi +} + +# Function to provide deployment instructions +deployment_instructions() { + print_success "Production setup completed!" + echo + print_status "Next steps for deployment:" + echo " 1. Run: make deploy-production" + echo " 2. Monitor deployment: kubectl get pods -A" + echo " 3. Get cluster credentials: az aks get-credentials --name --resource-group " + echo " 4. Access via Tailscale: kubectl get -n crs-webservice ingress" + echo + print_status "Useful commands:" + echo " - View logs: kubectl logs -n crs " + echo " - Scale nodes: Update TF_VAR_usr_node_count and run make deploy-production" + echo " - Cleanup: make clean" +} + +# Main execution +main() { + print_status "Starting production setup..." + + check_azure_cli + check_terraform + install_just + setup_service_principal + setup_config + setup_remote_state + + print_status "Configuration validation..." + if validate_config; then + deployment_instructions + else + print_error "Please fix configuration issues before proceeding" + exit 1 + fi +} + +# Run main function +main "$@" diff --git a/scripts/validate-setup.sh b/scripts/validate-setup.sh new file mode 100755 index 00000000..472efd17 --- /dev/null +++ b/scripts/validate-setup.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Setup Validation Script for Buttercup CRS +# This script validates the current setup and configuration + +set -e + +# Source common functions +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +echo "🔍 Validating Buttercup CRS setup..." + +# Check if running as root +check_not_root + +# Main execution +main() { + local total_errors=0 + + print_status "Starting setup validation..." + echo + + # Check tools + check_docker || total_errors=$((total_errors + 1)) + check_kubectl || total_errors=$((total_errors + 1)) + check_helm || total_errors=$((total_errors + 1)) + check_minikube + check_azure_cli + check_terraform + echo + + # Check configuration + check_config || total_errors=$((total_errors + 1)) + echo + + # Summary + if [ $total_errors -eq 0 ]; then + print_success "Setup validation completed successfully!" + print_status "Your environment is ready for deployment." + else + print_error "Setup validation completed with $total_errors error(s)" + print_status "Please fix the errors above before proceeding." + fi +} + +# Run main function +main "$@"