init bootstrap
This commit is contained in:
176
scripts/generate-secrets.ps1
Normal file
176
scripts/generate-secrets.ps1
Normal file
@@ -0,0 +1,176 @@
|
||||
# Bootstrap App - Secret Generation Script
|
||||
# This script generates cryptographically secure secrets for the Bootstrap App
|
||||
|
||||
Write-Host "Bootstrap App - Secret Generation Script" -ForegroundColor Green
|
||||
Write-Host "=========================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Function to generate random bytes and convert to hex
|
||||
function Generate-HexString {
|
||||
param([int]$Length)
|
||||
$bytes = New-Object byte[] $Length
|
||||
$rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new()
|
||||
$rng.GetBytes($bytes)
|
||||
$rng.Dispose()
|
||||
return [System.BitConverter]::ToString($bytes) -replace '-', ''
|
||||
}
|
||||
|
||||
# Function to generate random bytes and convert to base64
|
||||
function Generate-Base64String {
|
||||
param([int]$Length)
|
||||
$bytes = New-Object byte[] $Length
|
||||
$rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new()
|
||||
$rng.GetBytes($bytes)
|
||||
$rng.Dispose()
|
||||
return [System.Convert]::ToBase64String($bytes)
|
||||
}
|
||||
|
||||
# Generate secrets
|
||||
Write-Host "Generating cryptographically secure secrets..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$jwtSecret = Generate-Base64String -Length 64
|
||||
$appSecret = Generate-HexString -Length 32
|
||||
$appSecretCode = Generate-HexString -Length 32
|
||||
$encryptionKey = Generate-HexString -Length 16
|
||||
|
||||
# Display generated secrets
|
||||
Write-Host "Generated Secrets:" -ForegroundColor Cyan
|
||||
Write-Host "==================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "JWT_SECRET=" -NoNewline -ForegroundColor White
|
||||
Write-Host $jwtSecret -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host "APP_SECRET=" -NoNewline -ForegroundColor White
|
||||
Write-Host $appSecret -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host "APP_SECRET_CODE=" -NoNewline -ForegroundColor White
|
||||
Write-Host $appSecretCode -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host "ENCRYPTION_KEY=" -NoNewline -ForegroundColor White
|
||||
Write-Host $encryptionKey -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# Check if .env file exists
|
||||
$envFile = ".env"
|
||||
$envExists = Test-Path $envFile
|
||||
|
||||
if ($envExists) {
|
||||
Write-Host "Warning: .env file already exists!" -ForegroundColor Red
|
||||
$overwrite = Read-Host "Do you want to update it with new secrets? (y/N)"
|
||||
if ($overwrite -eq "y" -or $overwrite -eq "Y") {
|
||||
$updateFile = $true
|
||||
} else {
|
||||
$updateFile = $false
|
||||
Write-Host "Secrets generated but not written to file." -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
$createFile = Read-Host "Create .env file with these secrets? (Y/n)"
|
||||
if ($createFile -eq "" -or $createFile -eq "y" -or $createFile -eq "Y") {
|
||||
$updateFile = $true
|
||||
} else {
|
||||
$updateFile = $false
|
||||
Write-Host "Secrets generated but not written to file." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
if ($updateFile) {
|
||||
# Create or update .env file
|
||||
if ($envExists) {
|
||||
# Backup existing file
|
||||
$backupFile = ".env.backup." + (Get-Date -Format "yyyyMMdd-HHmmss")
|
||||
Copy-Item $envFile $backupFile
|
||||
Write-Host "Backed up existing .env to $backupFile" -ForegroundColor Green
|
||||
|
||||
# Read existing content and update secrets
|
||||
$content = Get-Content $envFile
|
||||
$newContent = @()
|
||||
|
||||
foreach ($line in $content) {
|
||||
if ($line -match "^JWT_SECRET=") {
|
||||
$newContent += "JWT_SECRET=$jwtSecret"
|
||||
} elseif ($line -match "^APP_SECRET=") {
|
||||
$newContent += "APP_SECRET=$appSecret"
|
||||
} elseif ($line -match "^APP_SECRET_CODE=") {
|
||||
$newContent += "APP_SECRET_CODE=$appSecretCode"
|
||||
} elseif ($line -match "^ENCRYPTION_KEY=") {
|
||||
$newContent += "ENCRYPTION_KEY=$encryptionKey"
|
||||
} else {
|
||||
$newContent += $line
|
||||
}
|
||||
}
|
||||
|
||||
$newContent | Out-File -FilePath $envFile -Encoding UTF8
|
||||
Write-Host "Updated .env file with new secrets" -ForegroundColor Green
|
||||
} else {
|
||||
# Create new .env file from template
|
||||
if (Test-Path ".env.example") {
|
||||
$template = Get-Content ".env.example"
|
||||
$newContent = @()
|
||||
|
||||
foreach ($line in $template) {
|
||||
if ($line -match "^JWT_SECRET=") {
|
||||
$newContent += "JWT_SECRET=$jwtSecret"
|
||||
} elseif ($line -match "^APP_SECRET=") {
|
||||
$newContent += "APP_SECRET=$appSecret"
|
||||
} elseif ($line -match "^APP_SECRET_CODE=") {
|
||||
$newContent += "APP_SECRET_CODE=$appSecretCode"
|
||||
} elseif ($line -match "^ENCRYPTION_KEY=") {
|
||||
$newContent += "ENCRYPTION_KEY=$encryptionKey"
|
||||
} else {
|
||||
$newContent += $line
|
||||
}
|
||||
}
|
||||
|
||||
$newContent | Out-File -FilePath $envFile -Encoding UTF8
|
||||
Write-Host "Created .env file from template with generated secrets" -ForegroundColor Green
|
||||
} else {
|
||||
# Create minimal .env file
|
||||
$minimalEnv = @(
|
||||
"# Bootstrap App Environment Configuration",
|
||||
"# Generated on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')",
|
||||
"",
|
||||
"# CRITICAL SECURITY SETTINGS (REQUIRED)",
|
||||
"JWT_SECRET=$jwtSecret",
|
||||
"APP_SECRET=$appSecret",
|
||||
"APP_SECRET_CODE=$appSecretCode",
|
||||
"ENCRYPTION_KEY=$encryptionKey",
|
||||
"",
|
||||
"# CORE APPLICATION SETTINGS",
|
||||
"DB_NAME=app.db",
|
||||
"PORT=3000",
|
||||
"CORS_ALLOWED_ORIGIN=http://localhost:5173",
|
||||
"DEFAULT_ADMIN_PASSWORD=change-this-password"
|
||||
)
|
||||
|
||||
$minimalEnv | Out-File -FilePath $envFile -Encoding UTF8
|
||||
Write-Host "Created minimal .env file with generated secrets" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Security Notes:" -ForegroundColor Red
|
||||
Write-Host "===============" -ForegroundColor Red
|
||||
Write-Host "1. Keep these secrets secure and never commit them to version control" -ForegroundColor Yellow
|
||||
Write-Host "2. Use different secrets for each environment (dev, staging, production)" -ForegroundColor Yellow
|
||||
Write-Host "3. Rotate secrets regularly in production environments" -ForegroundColor Yellow
|
||||
Write-Host "4. The ENCRYPTION_KEY is exactly 32 characters as required for AES-256" -ForegroundColor Yellow
|
||||
Write-Host "5. Change the DEFAULT_ADMIN_PASSWORD immediately after first login" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# Verify encryption key length
|
||||
if ($encryptionKey.Length -eq 32) { # 32 characters = 32 bytes when converted to []byte in Go
|
||||
Write-Host "✓ Encryption key length verified (32 characters = 32 bytes for AES-256)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "✗ Warning: Encryption key length is incorrect! Got $($encryptionKey.Length) chars, expected 32" -ForegroundColor Red
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Next steps:" -ForegroundColor Cyan
|
||||
Write-Host "1. Review and customize the .env file if needed" -ForegroundColor White
|
||||
Write-Host "2. Build and run the application: go run cmd/api/main.go" -ForegroundColor White
|
||||
Write-Host "3. Change the default admin password on first login" -ForegroundColor White
|
||||
Write-Host "4. Access the API documentation at: http://localhost:3000/swagger/" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "Happy coding! 🚀" -ForegroundColor Green
|
||||
163
scripts/generate-secrets.sh
Normal file
163
scripts/generate-secrets.sh
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bootstrap App - Secret Generation Script
|
||||
# This script generates cryptographically secure secrets for the Bootstrap App
|
||||
|
||||
echo "Bootstrap App - Secret Generation Script"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to generate hex string
|
||||
generate_hex_string() {
|
||||
local length=$1
|
||||
openssl rand -hex $length 2>/dev/null || xxd -l $length -p /dev/urandom | tr -d '\n'
|
||||
}
|
||||
|
||||
# Function to generate base64 string
|
||||
generate_base64_string() {
|
||||
local length=$1
|
||||
openssl rand -base64 $length 2>/dev/null || dd if=/dev/urandom bs=$length count=1 2>/dev/null | base64 | tr -d '\n'
|
||||
}
|
||||
|
||||
# Check if required tools are available
|
||||
check_dependencies() {
|
||||
if ! command -v openssl >/dev/null 2>&1; then
|
||||
if ! command -v xxd >/dev/null 2>&1; then
|
||||
echo -e "${RED}Error: Neither openssl nor xxd is available. Please install one of them.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Generate secrets
|
||||
echo -e "${YELLOW}Generating cryptographically secure secrets...${NC}"
|
||||
echo ""
|
||||
|
||||
check_dependencies
|
||||
|
||||
JWT_SECRET=$(generate_base64_string 64)
|
||||
APP_SECRET=$(generate_hex_string 32)
|
||||
APP_SECRET_CODE=$(generate_hex_string 32)
|
||||
ENCRYPTION_KEY=$(generate_hex_string 16)
|
||||
|
||||
# Display generated secrets
|
||||
echo -e "${CYAN}Generated Secrets:${NC}"
|
||||
echo -e "${CYAN}==================${NC}"
|
||||
echo ""
|
||||
echo -e "${WHITE}JWT_SECRET=${NC}${YELLOW}$JWT_SECRET${NC}"
|
||||
echo ""
|
||||
echo -e "${WHITE}APP_SECRET=${NC}${YELLOW}$APP_SECRET${NC}"
|
||||
echo ""
|
||||
echo -e "${WHITE}APP_SECRET_CODE=${NC}${YELLOW}$APP_SECRET_CODE${NC}"
|
||||
echo ""
|
||||
echo -e "${WHITE}ENCRYPTION_KEY=${NC}${YELLOW}$ENCRYPTION_KEY${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if .env file exists
|
||||
ENV_FILE=".env"
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
echo -e "${RED}Warning: .env file already exists!${NC}"
|
||||
read -p "Do you want to update it with new secrets? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
UPDATE_FILE=true
|
||||
else
|
||||
UPDATE_FILE=false
|
||||
echo -e "${YELLOW}Secrets generated but not written to file.${NC}"
|
||||
fi
|
||||
else
|
||||
read -p "Create .env file with these secrets? (Y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||
UPDATE_FILE=false
|
||||
echo -e "${YELLOW}Secrets generated but not written to file.${NC}"
|
||||
else
|
||||
UPDATE_FILE=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$UPDATE_FILE" = true ]; then
|
||||
# Create or update .env file
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
# Backup existing file
|
||||
BACKUP_FILE=".env.backup.$(date +%Y%m%d-%H%M%S)"
|
||||
cp "$ENV_FILE" "$BACKUP_FILE"
|
||||
echo -e "${GREEN}Backed up existing .env to $BACKUP_FILE${NC}"
|
||||
|
||||
# Update secrets in existing file
|
||||
sed -i.tmp "s/^JWT_SECRET=.*/JWT_SECRET=$JWT_SECRET/" "$ENV_FILE"
|
||||
sed -i.tmp "s/^APP_SECRET=.*/APP_SECRET=$APP_SECRET/" "$ENV_FILE"
|
||||
sed -i.tmp "s/^APP_SECRET_CODE=.*/APP_SECRET_CODE=$APP_SECRET_CODE/" "$ENV_FILE"
|
||||
sed -i.tmp "s/^ENCRYPTION_KEY=.*/ENCRYPTION_KEY=$ENCRYPTION_KEY/" "$ENV_FILE"
|
||||
rm -f "$ENV_FILE.tmp"
|
||||
|
||||
echo -e "${GREEN}Updated .env file with new secrets${NC}"
|
||||
else
|
||||
# Create new .env file from template
|
||||
if [ -f ".env.example" ]; then
|
||||
cp ".env.example" "$ENV_FILE"
|
||||
|
||||
# Replace placeholder values with generated secrets
|
||||
sed -i.tmp "s/^JWT_SECRET=.*/JWT_SECRET=$JWT_SECRET/" "$ENV_FILE"
|
||||
sed -i.tmp "s/^APP_SECRET=.*/APP_SECRET=$APP_SECRET/" "$ENV_FILE"
|
||||
sed -i.tmp "s/^APP_SECRET_CODE=.*/APP_SECRET_CODE=$APP_SECRET_CODE/" "$ENV_FILE"
|
||||
sed -i.tmp "s/^ENCRYPTION_KEY=.*/ENCRYPTION_KEY=$ENCRYPTION_KEY/" "$ENV_FILE"
|
||||
rm -f "$ENV_FILE.tmp"
|
||||
|
||||
echo -e "${GREEN}Created .env file from template with generated secrets${NC}"
|
||||
else
|
||||
# Create minimal .env file
|
||||
cat > "$ENV_FILE" << EOF
|
||||
# Bootstrap App Environment Configuration
|
||||
# Generated on $(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# CRITICAL SECURITY SETTINGS (REQUIRED)
|
||||
JWT_SECRET=$JWT_SECRET
|
||||
APP_SECRET=$APP_SECRET
|
||||
APP_SECRET_CODE=$APP_SECRET_CODE
|
||||
ENCRYPTION_KEY=$ENCRYPTION_KEY
|
||||
|
||||
# CORE APPLICATION SETTINGS
|
||||
DB_NAME=app.db
|
||||
PORT=3000
|
||||
CORS_ALLOWED_ORIGIN=http://localhost:5173
|
||||
DEFAULT_ADMIN_PASSWORD=change-this-password
|
||||
EOF
|
||||
echo -e "${GREEN}Created minimal .env file with generated secrets${NC}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${RED}Security Notes:${NC}"
|
||||
echo -e "${RED}===============${NC}"
|
||||
echo -e "${YELLOW}1. Keep these secrets secure and never commit them to version control${NC}"
|
||||
echo -e "${YELLOW}2. Use different secrets for each environment (dev, staging, production)${NC}"
|
||||
echo -e "${YELLOW}3. Rotate secrets regularly in production environments${NC}"
|
||||
echo -e "${YELLOW}4. The ENCRYPTION_KEY is exactly 32 characters as required for AES-256${NC}"
|
||||
echo -e "${YELLOW}5. Change the DEFAULT_ADMIN_PASSWORD immediately after first login${NC}"
|
||||
echo ""
|
||||
|
||||
# Verify encryption key length
|
||||
if [ ${#ENCRYPTION_KEY} -eq 32 ]; then
|
||||
echo -e "${GREEN}✓ Encryption key length verified (32 characters = 32 bytes for AES-256)${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ Warning: Encryption key length is incorrect! Got ${#ENCRYPTION_KEY} chars, expected 32${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}Next steps:${NC}"
|
||||
echo -e "${WHITE}1. Review and customize the .env file if needed${NC}"
|
||||
echo -e "${WHITE}2. Build and run the application: go run cmd/api/main.go${NC}"
|
||||
echo -e "${WHITE}3. Change the default admin password on first login${NC}"
|
||||
echo -e "${WHITE}4. Access the API documentation at: http://localhost:3000/swagger/${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN}Happy coding! 🚀${NC}"
|
||||
Reference in New Issue
Block a user