From 5adfeeab87879fb52cd92d830ca17906aa03cff8 Mon Sep 17 00:00:00 2001 From: Richard Kiene Date: Fri, 22 Aug 2025 16:02:15 -0700 Subject: [PATCH 1/2] Enable multi-architecture Docker builds for arm64 and amd64 Add platforms specification to Docker build-push-action to build for both linux/amd64 and linux/arm64 architectures. This allows the devcontainer to run natively on Apple Silicon Macs without Rosetta emulation. --- .github/workflows/build-image.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 50f7c6b..8df2e0c 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -31,6 +31,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to the Container registry uses: docker/login-action@v3 with: @@ -54,6 +60,7 @@ jobs: uses: docker/build-push-action@v5 with: context: ./docker-image + platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} From 0e78716c21e15252fb47933f2afe29131bde7079 Mon Sep 17 00:00:00 2001 From: Richard Kiene Date: Fri, 22 Aug 2025 16:15:31 -0700 Subject: [PATCH 2/2] Simplify 1Password setup by removing auto-creation logic - Remove automatic service account creation from setup-1password.sh - Update script to only verify authentication status and provide manual instructions - Improve documentation in .env.example with clear step-by-step instructions - Update README with detailed service account creation guide - Focus on manual token configuration for better security and predictability --- .devcontainer/.env.example | 45 ++++--- README.md | 32 +++-- docker-image/scripts/setup-1password.sh | 155 +++++------------------- 3 files changed, 74 insertions(+), 158 deletions(-) diff --git a/.devcontainer/.env.example b/.devcontainer/.env.example index 52f0db2..664891a 100644 --- a/.devcontainer/.env.example +++ b/.devcontainer/.env.example @@ -20,35 +20,34 @@ MOUNT_HOST_GIT_CONFIG=false # ============================================================================ # 1PASSWORD CLI CONFIGURATION # ============================================================================ +# The 1Password CLI is pre-installed in the container. To authenticate it, +# you need to provide either a Service Account token or Connect Server credentials. -# Option 1: Automatic Service Account Creation (Recommended for small teams) +# Option 1: Service Account Token (Recommended for DevContainers) # --------------------------------------------------------------------------- -# Enable automatic creation of a 1Password service account when the container starts -# Requires: 1Password CLI installed on host and signed in (op signin completed) -OP_CREATE_SERVICE_ACCOUNT=false - -# Configure the automatically created service account: -# Token lifetime (examples: 7d, 30d, 90d, 1y) -OP_SA_EXPIRES_IN=30d - -# Restrict to specific vaults (comma-separated, leave empty for all vaults) -# Example: OP_SA_VAULTS=Development,Staging,Production -OP_SA_VAULTS= - -# Custom name for the service account (defaults to: devcontainer--) -# Leave empty to auto-generate based on repository name -OP_SA_NAME= - -# Option 2: Manual Service Account Token -# --------------------------------------------------------------------------- -# If you have an existing service account token, set it here -# Create one with: op service-account create my-dev-account --expires-in 30d +# Service accounts provide secure, scoped access without requiring interactive signin. +# +# To create a service account on your host machine: +# 1. Install 1Password CLI: https://developer.1password.com/docs/cli/get-started +# 2. Sign in to your account: op signin +# 3. Create a service account: +# op service-account create "devcontainer-$(basename $(pwd))" --expires-in 30d +# 4. Copy the token (starts with 'ops_') and paste it below +# +# For vault-specific access (more secure): +# op service-account create "my-dev" --expires-in 30d --vault Development:read_items +# +# The token will be securely passed to the container for CLI authentication. OP_SERVICE_ACCOUNT_TOKEN= -# Option 3: 1Password Connect Server (For larger teams) +# Option 2: 1Password Connect Server (For Teams/Enterprise) # --------------------------------------------------------------------------- -# If you have a 1Password Connect Server infrastructure +# Connect Server provides centralized access management for teams. +# Contact your IT admin for these values if using Connect Server. +# +# Server URL (e.g., https://connect.company.com) OP_CONNECT_HOST= +# Connect token for authentication OP_CONNECT_TOKEN= # ============================================================================ diff --git a/README.md b/README.md index d668093..26e3f23 100644 --- a/README.md +++ b/README.md @@ -110,27 +110,43 @@ staging.example.com #### 1Password Integration -**Option 1: Service Account** (Recommended) +The 1Password CLI is pre-installed but requires authentication configuration. + +**Option 1: Service Account** (Recommended for DevContainers) + +Service accounts provide secure, non-interactive authentication perfect for development containers. + ```bash -# Create on host -op service-account create devcontainer --expires-in 30d -# Add token to .env -OP_SERVICE_ACCOUNT_TOKEN=ops_... +# On your host machine: +# 1. Install 1Password CLI: https://developer.1password.com/docs/cli/get-started +# 2. Sign in: op signin +# 3. Create a service account: +op service-account create "devcontainer-$(basename $(pwd))" --expires-in 30d + +# 4. Copy the token (starts with 'ops_') to .devcontainer/.env: +OP_SERVICE_ACCOUNT_TOKEN=ops_YOUR_TOKEN_HERE + +# For vault-specific access (more secure): +op service-account create "my-dev" --expires-in 30d --vault Development:read_items ``` -**Option 2: Connect Server** +**Option 2: Connect Server** (For Teams/Enterprise) ```bash +# In .devcontainer/.env: OP_CONNECT_HOST=https://connect.company.com -OP_CONNECT_TOKEN=... +OP_CONNECT_TOKEN=your-connect-token ``` **Usage in container**: ```bash -# Inject environment variables +# Inject environment variables from 1Password op run --env-file=prod.env -- npm start # Read specific secrets export API_KEY=$(op read "op://vault/item/field") + +# Use with git for secure commit signing +op plugin init git ``` ## đŸ—ī¸ Architecture diff --git a/docker-image/scripts/setup-1password.sh b/docker-image/scripts/setup-1password.sh index 0182bb5..278e80f 100644 --- a/docker-image/scripts/setup-1password.sh +++ b/docker-image/scripts/setup-1password.sh @@ -1,24 +1,25 @@ #!/bin/bash # Setup 1Password CLI in the devcontainer -# This script handles service account token creation and configuration +# This script verifies 1Password CLI authentication status set -e -echo "🔐 Setting up 1Password CLI..." +echo "🔐 Checking 1Password CLI authentication..." # Check if we already have a service account token if [ -n "$OP_SERVICE_ACCOUNT_TOKEN" ]; then - echo "✅ Using existing 1Password service account token" + echo "✅ Using 1Password service account token" # Test the token if op vault list &>/dev/null; then echo "✅ 1Password CLI authenticated successfully" exit 0 else - echo "âš ī¸ Existing service account token appears invalid" + echo "âš ī¸ Service account token appears invalid" + echo " Please verify your OP_SERVICE_ACCOUNT_TOKEN is correct" fi fi -# Check for Connect Server configuration (secondary option) +# Check for Connect Server configuration if [ -n "$OP_CONNECT_HOST" ] && [ -n "$OP_CONNECT_TOKEN" ]; then echo "✅ Using 1Password Connect Server at $OP_CONNECT_HOST" # Test the connection @@ -27,128 +28,28 @@ if [ -n "$OP_CONNECT_HOST" ] && [ -n "$OP_CONNECT_TOKEN" ]; then exit 0 else echo "âš ī¸ Connect Server authentication failed" + echo " Please verify your OP_CONNECT_HOST and OP_CONNECT_TOKEN are correct" fi fi -# If we get here, we need to create a service account token -# Check if the host has 1Password CLI available and authenticated -if [ -n "$OP_CREATE_SERVICE_ACCOUNT" ] && [ "$OP_CREATE_SERVICE_ACCOUNT" = "true" ]; then - echo "" - echo "📝 Attempting to create a new 1Password service account..." - echo "" - - # Use environment variables to configure the service account - EXPIRES_IN="${OP_SA_EXPIRES_IN:-30d}" # Default 30 days - VAULTS="${OP_SA_VAULTS:-}" # Comma-separated list of vault names - - # Generate a unique name with repository info if not provided - if [ -n "$OP_SA_NAME" ]; then - ACCOUNT_NAME="$OP_SA_NAME" - else - # Try to get repository name from git - REPO_NAME="" - if [ -d "/workspace/.git" ]; then - # Get the repository name from the remote URL - REMOTE_URL=$(git -C /workspace config --get remote.origin.url 2>/dev/null || echo "") - if [ -n "$REMOTE_URL" ]; then - # Extract repo name from URL (works with both HTTPS and SSH URLs) - REPO_NAME=$(basename -s .git "$REMOTE_URL" 2>/dev/null || echo "") - fi - fi - - # If we couldn't get repo name, try workspace folder name - if [ -z "$REPO_NAME" ]; then - REPO_NAME=$(basename "/workspace" 2>/dev/null || echo "workspace") - fi - - # Create unique name: repo-name-YYYYMMDD-HHMMSS - TIMESTAMP=$(date +%Y%m%d-%H%M%S) - ACCOUNT_NAME="devcontainer-${REPO_NAME}-${TIMESTAMP}" - fi - - # Check if we can run op on the host - if ! command -v op &> /dev/null; then - echo "âš ī¸ 1Password CLI not found on host system" - echo " Please install 1Password CLI on your host to auto-create service accounts" - echo " Or set OP_SERVICE_ACCOUNT_TOKEN manually" - exit 0 - fi - - # Check if user is signed in on the host - if ! op account list &>/dev/null; then - echo "âš ī¸ Not signed in to 1Password CLI on host" - echo " Please run 'op signin' on your host first" - echo " Or set OP_SERVICE_ACCOUNT_TOKEN manually" - exit 0 - fi - - echo "Creating service account with:" - echo " â€ĸ Name: $ACCOUNT_NAME" - echo " â€ĸ Expires: $EXPIRES_IN" - if [ -n "$VAULTS" ]; then - echo " â€ĸ Vaults: $VAULTS" - else - echo " â€ĸ Vaults: All vaults (no restriction)" - fi - - # Build the op command - OP_CMD="op service-account create $ACCOUNT_NAME --expires-in $EXPIRES_IN" - - # Add vault restrictions if specified - if [ -n "$VAULTS" ]; then - IFS=',' read -ra VAULT_ARRAY <<< "$VAULTS" - for vault in "${VAULT_ARRAY[@]}"; do - OP_CMD="$OP_CMD --vault $vault:read_items" - done - fi - - # Create the service account and capture the token - if SERVICE_ACCOUNT_OUTPUT=$(eval $OP_CMD 2>&1); then - # Extract the token from the output - TOKEN=$(echo "$SERVICE_ACCOUNT_OUTPUT" | grep -oP 'ops_[A-Za-z0-9_-]+' | head -1) - - if [ -n "$TOKEN" ]; then - # Save the token to a file in the container - echo "$TOKEN" > /home/node/.op_service_account_token - chmod 600 /home/node/.op_service_account_token - - # Export for current session - export OP_SERVICE_ACCOUNT_TOKEN="$TOKEN" - - echo "" - echo "✅ Service account created successfully!" - echo " Token saved to container (will persist for this container's lifetime)" - echo "" - echo " To use this token in future containers, add to your host environment:" - echo " export OP_SERVICE_ACCOUNT_TOKEN=\"$TOKEN\"" - echo "" - else - echo "âš ī¸ Failed to extract service account token from output" - fi - else - echo "âš ī¸ Failed to create service account: $SERVICE_ACCOUNT_OUTPUT" - fi -fi - -# Final check - if we still don't have authentication, provide instructions -if ! op vault list &>/dev/null 2>&1; then - echo "" - echo "â„šī¸ 1Password CLI is not authenticated. To use it, you can:" - echo "" - echo "Option 1: Create a service account on your host and set the token:" - echo " op service-account create my-dev-account --expires-in 30d" - echo " export OP_SERVICE_ACCOUNT_TOKEN=\"\"" - echo "" - echo "Option 2: Use 1Password Connect Server:" - echo " export OP_CONNECT_HOST=\"https://your-connect-server.example.com\"" - echo " export OP_CONNECT_TOKEN=\"\"" - echo "" - echo "Option 3: Enable auto-creation in your next container:" - echo " export OP_CREATE_SERVICE_ACCOUNT=true" - echo " export OP_SA_EXPIRES_IN=7d # Optional: token lifetime" - echo " export OP_SA_VAULTS=Development,Staging # Optional: vault restrictions" - echo "" -else - echo "✅ 1Password CLI is ready to use!" - echo " Example: op run --env-file=.env.prod -- npm start" -fi \ No newline at end of file +# If we get here, 1Password is not configured +echo "" +echo "â„šī¸ 1Password CLI is not authenticated. To use it:" +echo "" +echo "Option 1: Create a service account (recommended for devcontainers):" +echo " 1. On your host machine, run:" +echo " op service-account create \"devcontainer-\$(basename \$(pwd))\" --expires-in 30d" +echo " 2. Copy the token (starts with 'ops_')" +echo " 3. Add to your .devcontainer/.env file:" +echo " OP_SERVICE_ACCOUNT_TOKEN=ops_YOUR_TOKEN_HERE" +echo " 4. Rebuild the devcontainer" +echo "" +echo "Option 2: Use 1Password Connect Server (for teams):" +echo " Add to your .devcontainer/.env file:" +echo " OP_CONNECT_HOST=https://your-connect-server.example.com" +echo " OP_CONNECT_TOKEN=your-connect-token" +echo "" +echo "Once configured, you can use commands like:" +echo " op run --env-file=.env.prod -- npm start" +echo " op read \"op://vault/item/field\"" +echo "" \ No newline at end of file