Feature: credentials page & vaultwarden compose setup (#3534)
Co-authored-by: Suchintan <suchintan@users.noreply.github.com>
This commit is contained in:
30
.env.example
30
.env.example
@@ -112,4 +112,32 @@ ANALYTICS_ID="anonymous"
|
|||||||
OP_SERVICE_ACCOUNT_TOKEN=""
|
OP_SERVICE_ACCOUNT_TOKEN=""
|
||||||
|
|
||||||
# Enable recording skyvern logs as artifacts
|
# Enable recording skyvern logs as artifacts
|
||||||
ENABLE_LOG_ARTIFACTS=false
|
ENABLE_LOG_ARTIFACTS=false
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SKYVERN BITWARDEN CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
# Your organization ID in official Bitwarden server or vaultwarden (if using organizations)
|
||||||
|
SKYVERN_AUTH_BITWARDEN_ORGANIZATION_ID=your-org-id-here
|
||||||
|
|
||||||
|
# These should match the values for bitwarden cli server for consistency
|
||||||
|
SKYVERN_AUTH_BITWARDEN_MASTER_PASSWORD=your-master-password-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_CLIENT_ID=user.your-client-id-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET=your-client-secret-here
|
||||||
|
|
||||||
|
# The CLI server will run on localhost:8002 by default
|
||||||
|
# Optional, because by default Bitwarden is used directly
|
||||||
|
# BITWARDEN_SERVER=http://localhost
|
||||||
|
# BITWARDEN_SERVER_PORT=8002
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# OPTIONAL: ADDITIONAL SKYVERN CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
# If you need to override the default Bitwarden server settings in Skyvern
|
||||||
|
# These will be automatically set by the Docker Compose, but you can override them here
|
||||||
|
|
||||||
|
# Maximum number of retries for Bitwarden operations
|
||||||
|
# BITWARDEN_MAX_RETRIES=3
|
||||||
|
|
||||||
|
# Timeout in seconds for Bitwarden operations
|
||||||
|
# BITWARDEN_TIMEOUT_SECONDS=60
|
||||||
|
|||||||
27
.gitattributes
vendored
Normal file
27
.gitattributes
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Set default behavior to automatically normalize line endings
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Force Unix LF line endings for shell scripts
|
||||||
|
*.sh text eol=lf
|
||||||
|
bitwarden-cli-server/entrypoint.sh text eol=lf
|
||||||
|
|
||||||
|
# Force Unix LF line endings for Python files
|
||||||
|
*.py text eol=lf
|
||||||
|
|
||||||
|
# Force Unix LF line endings for Docker files
|
||||||
|
Dockerfile text eol=lf
|
||||||
|
*.dockerfile text eol=lf
|
||||||
|
|
||||||
|
# Force Unix LF line endings for YAML and config files
|
||||||
|
*.yml text eol=lf
|
||||||
|
*.yaml text eol=lf
|
||||||
|
*.json text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
|
||||||
|
# Binary files
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.jpeg binary
|
||||||
|
*.gif binary
|
||||||
|
*.ico binary
|
||||||
|
*.pdf binary
|
||||||
10
.yamlfmt
Normal file
10
.yamlfmt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# yamlfmt configuration
|
||||||
|
# Force Unix LF line endings for all YAML files
|
||||||
|
line_ending: lf
|
||||||
|
|
||||||
|
# Additional formatting options
|
||||||
|
formatter:
|
||||||
|
type: basic
|
||||||
|
indent: 2
|
||||||
|
include_document_start: false
|
||||||
|
pad_line_comments: 1
|
||||||
29
bitwarden-cli-server/Dockerfile
Normal file
29
bitwarden-cli-server/Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
# Install Bitwarden CLI
|
||||||
|
RUN apk add --no-cache curl bash && \
|
||||||
|
npm install -g @bitwarden/cli
|
||||||
|
|
||||||
|
# Create non-root user for security
|
||||||
|
# Create directory for Bitwarden config
|
||||||
|
RUN addgroup -g 1001 -S bw && adduser -S bw -u 1001 -G bw && \
|
||||||
|
mkdir -p /app/.config && \
|
||||||
|
chown -R bw:bw /app/.config
|
||||||
|
|
||||||
|
# Copy entrypoint script
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER bw
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Expose port for bw serve
|
||||||
|
EXPOSE 8087
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8087/status || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
104
bitwarden-cli-server/README.md
Normal file
104
bitwarden-cli-server/README.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Bitwarden CLI Server for Skyvern
|
||||||
|
|
||||||
|
This Docker setup provides a Bitwarden CLI server with `bw serve` functionality that enables Skyvern to work with vaultwarden (or official Bitwarden) instances.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
Usual setup (in cloud):
|
||||||
|
Skyvern → official Bitwarden
|
||||||
|
|
||||||
|
Local from docker compose:
|
||||||
|
Skyvern → bw serve (CLI Server) → vaultwarden Server
|
||||||
|
```
|
||||||
|
|
||||||
|
The CLI server acts as a bridge between Skyvern and vaultwarden, providing the REST API endpoints that Skyvern expects.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
This container is part of the main Skyvern Docker Compose setup. Configure your environment variables in the main `.env` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Skyvern Bitwarden Configuration
|
||||||
|
SKYVERN_AUTH_BITWARDEN_ORGANIZATION_ID=your-org-id-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_MASTER_PASSWORD=your-master-password-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_CLIENT_ID=user.your-client-id-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET=your-client-secret-here
|
||||||
|
|
||||||
|
# Vaultwarden Configuration
|
||||||
|
BW_HOST=https://your-vaultwarden-server.com
|
||||||
|
BW_CLIENTID=${SKYVERN_AUTH_BITWARDEN_CLIENT_ID}
|
||||||
|
BW_CLIENTSECRET=${SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET}
|
||||||
|
BW_PASSWORD=${SKYVERN_AUTH_BITWARDEN_MASTER_PASSWORD}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then start the service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d bitwarden-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Endpoints
|
||||||
|
|
||||||
|
Once running, the CLI server provides these endpoints on port 8002:
|
||||||
|
|
||||||
|
- `GET /status` - Check server status
|
||||||
|
- `POST /unlock` - Unlock vault
|
||||||
|
- `GET /list/object/items` - List vault items
|
||||||
|
- `GET /object/item/{id}` - Get specific item
|
||||||
|
- `POST /object/item` - Create new item
|
||||||
|
- `GET /object/template/item` - Get item template
|
||||||
|
- And more...
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Container won't start
|
||||||
|
|
||||||
|
1. **Check logs**:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.bitwarden.yml logs bitwarden-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Common issues**:
|
||||||
|
- Invalid API credentials
|
||||||
|
- Wrong vaultwarden server URL
|
||||||
|
- Network connectivity issues
|
||||||
|
- Incorrect master password
|
||||||
|
|
||||||
|
### Health check fails
|
||||||
|
|
||||||
|
The container includes a health check that calls `/status`. If it fails:
|
||||||
|
|
||||||
|
1. Check if the CLI server is actually running inside the container
|
||||||
|
2. Verify the unlock process succeeded
|
||||||
|
3. Check network configuration
|
||||||
|
|
||||||
|
### API calls fail
|
||||||
|
|
||||||
|
1. **Test the CLI server directly**:
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
curl http://localhost:8002/status
|
||||||
|
|
||||||
|
# List items (after unlock)
|
||||||
|
curl http://localhost:8002/list/object/items
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check Skyvern configuration**:
|
||||||
|
- Ensure `BITWARDEN_SERVER` points to the CLI server
|
||||||
|
- Verify `BITWARDEN_SERVER_PORT` is correct
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- The container runs as a non-root user for security
|
||||||
|
- Only binds to localhost by default
|
||||||
|
- API credentials are passed via environment variables
|
||||||
|
- Consider using Docker secrets for production deployments
|
||||||
|
|
||||||
|
## Production Considerations
|
||||||
|
|
||||||
|
1. **Secrets Management**: Use Docker secrets or external secret management
|
||||||
|
2. **Monitoring**: Add proper logging and monitoring
|
||||||
|
3. **Backup**: Ensure your vaultwarden instance is properly backed up
|
||||||
|
4. **Updates**: Regularly update the Bitwarden CLI version
|
||||||
|
5. **Network Security**: Use proper network isolation and firewalls
|
||||||
183
bitwarden-cli-server/entrypoint.sh
Normal file
183
bitwarden-cli-server/entrypoint.sh
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Color codes for better logging
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Update log function to use color codes
|
||||||
|
log() {
|
||||||
|
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Starting entrypoint script..."
|
||||||
|
log "Current user: $(whoami)"
|
||||||
|
log "Current directory: $(pwd)"
|
||||||
|
|
||||||
|
# Check required environment variables
|
||||||
|
if [[ -z "${BW_HOST:-}" ]]; then
|
||||||
|
log_error "BW_HOST environment variable is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${BW_CLIENTID:-}" ]]; then
|
||||||
|
log_error "BW_CLIENTID environment variable is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${BW_CLIENTSECRET:-}" ]]; then
|
||||||
|
log_error "BW_CLIENTSECRET environment variable is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${BW_PASSWORD:-}" ]]; then
|
||||||
|
log_error "BW_PASSWORD environment variable is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test network connectivity first
|
||||||
|
log "Testing connectivity to vaultwarden server: $BW_HOST"
|
||||||
|
if ! curl -s --connect-timeout 10 "$BW_HOST" > /dev/null; then
|
||||||
|
log_warning "Cannot reach $BW_HOST - this might be normal if the server doesn't respond to GET requests"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Logout first to clear any existing session
|
||||||
|
log "Logging out to clear any existing session..."
|
||||||
|
bw logout > /dev/null 2>&1 || true # Ignore errors if not logged in
|
||||||
|
|
||||||
|
# Configure Bitwarden CLI to use vaultwarden server
|
||||||
|
log "Configuring Bitwarden CLI to use server: $BW_HOST"
|
||||||
|
|
||||||
|
# Temporarily disable pipefail to capture the output properly
|
||||||
|
set +e
|
||||||
|
config_output=$(bw config server "$BW_HOST" 2>&1)
|
||||||
|
config_result=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
log "Config command result: $config_result"
|
||||||
|
log "Config command output: $config_output"
|
||||||
|
|
||||||
|
if [[ $config_result -ne 0 ]]; then
|
||||||
|
log_error "Failed to configure server. Error output:"
|
||||||
|
log_error "$config_output"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Server configuration successful"
|
||||||
|
|
||||||
|
# Login using API key with retry logic for rate limiting
|
||||||
|
log "Logging in to Bitwarden using API key..."
|
||||||
|
|
||||||
|
# Retry login with exponential backoff
|
||||||
|
max_retries=3
|
||||||
|
retry_count=0
|
||||||
|
login_success=false
|
||||||
|
|
||||||
|
while [[ $retry_count -lt $max_retries ]]; do
|
||||||
|
if [[ $retry_count -gt 0 ]]; then
|
||||||
|
delay=$((retry_count * retry_count * 5)) # 5, 20, 45 seconds
|
||||||
|
log "Rate limited. Waiting ${delay} seconds before retry $((retry_count + 1))/$max_retries..."
|
||||||
|
sleep $delay
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
login_output=$(bw login --apikey 2>&1)
|
||||||
|
login_result=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
log "Login attempt $((retry_count + 1)): result=$login_result"
|
||||||
|
log "Login output: '$login_output'"
|
||||||
|
|
||||||
|
if [[ $login_result -eq 0 ]]; then
|
||||||
|
login_success=true
|
||||||
|
break
|
||||||
|
elif [[ "$login_output" == *"Rate limit exceeded"* ]]; then
|
||||||
|
log_warning "Rate limit exceeded on attempt $((retry_count + 1))"
|
||||||
|
((retry_count++))
|
||||||
|
else
|
||||||
|
log_error "Failed to login with API key. Error output:"
|
||||||
|
log_error "$login_output"
|
||||||
|
log_error "Please check:"
|
||||||
|
log_error "1. BW_HOST is correct and accessible: $BW_HOST"
|
||||||
|
log_error "2. BW_CLIENTID is valid: ${BW_CLIENTID:0:20}..."
|
||||||
|
log_error "3. BW_CLIENTSECRET is correct"
|
||||||
|
log_error "4. API key is enabled in vaultwarden"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$login_success" != "true" ]]; then
|
||||||
|
log_error "Failed to login after $max_retries attempts due to rate limiting"
|
||||||
|
log_error "Please wait a few minutes and try again"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Successfully logged in"
|
||||||
|
|
||||||
|
# Now unlock to get the session token
|
||||||
|
log "Unlocking vault to get session token..."
|
||||||
|
set +e
|
||||||
|
unlock_output=$(bw unlock --passwordenv BW_PASSWORD --raw 2>&1)
|
||||||
|
unlock_result=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
log "Unlock command result: $unlock_result"
|
||||||
|
log "Unlock command output: '$unlock_output'"
|
||||||
|
|
||||||
|
if [[ $unlock_result -ne 0 ]]; then
|
||||||
|
log_error "Failed to unlock vault. Error output:"
|
||||||
|
log_error "$unlock_output"
|
||||||
|
log_error "Please check BW_PASSWORD is correct"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract session token from unlock output
|
||||||
|
export BW_SESSION="$unlock_output"
|
||||||
|
log "Session token length: ${#BW_SESSION}"
|
||||||
|
|
||||||
|
if [[ -z "$BW_SESSION" ]]; then
|
||||||
|
log_error "Session token is empty after unlock"
|
||||||
|
log_error "Raw unlock output was: '$unlock_output'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Vault unlocked successfully"
|
||||||
|
|
||||||
|
# Sync vault
|
||||||
|
log "Syncing vault..."
|
||||||
|
bw sync --session "$BW_SESSION" > /dev/null 2>&1 || {
|
||||||
|
log_warning "Sync failed, but continuing anyway"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success "Vault sync completed"
|
||||||
|
|
||||||
|
# Start the server
|
||||||
|
log "Starting Bitwarden CLI server on port 8087..."
|
||||||
|
log "Server will be accessible at http://localhost:8087"
|
||||||
|
log "Available endpoints:"
|
||||||
|
log " - GET /status - Check server status"
|
||||||
|
log " - POST /unlock - Unlock vault"
|
||||||
|
log " - GET /list/object/items - List vault items"
|
||||||
|
log " - GET /object/item/{id} - Get specific item"
|
||||||
|
log " - And more..."
|
||||||
|
|
||||||
|
# Start bw serve with proper error handling
|
||||||
|
exec bw serve --hostname 0.0.0.0 --port 8087 --session "$BW_SESSION" || {
|
||||||
|
log_error "Failed to start Bitwarden CLI server"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
@@ -114,10 +114,11 @@ services:
|
|||||||
# Bitwarden Settings
|
# Bitwarden Settings
|
||||||
# If you are looking to integrate Skyvern with a password manager (eg Bitwarden), you can use the following environment variables.
|
# If you are looking to integrate Skyvern with a password manager (eg Bitwarden), you can use the following environment variables.
|
||||||
# - BITWARDEN_SERVER=http://localhost # OPTIONAL IF YOU ARE SELF HOSTING BITWARDEN
|
# - BITWARDEN_SERVER=http://localhost # OPTIONAL IF YOU ARE SELF HOSTING BITWARDEN
|
||||||
# - BITWARDEN_SERVER_PORT=8002 # OPTIONAL IF YOU ARE SELF HOSTING BITWARDEN
|
# - BITWARDEN_SERVER_PORT=8002 # IF YOU ARE SELF HOSTING BITWARDEN AND USE THIS COMPOSE FILE, PORT IS 8002 UNLESS CHANGED
|
||||||
# - BITWARDEN_CLIENT_ID=FILL_ME_IN_PLEASE
|
# - SKYVERN_AUTH_BITWARDEN_ORGANIZATION_ID=your-org-id-here
|
||||||
# - BITWARDEN_CLIENT_SECRET=FILL_ME_IN_PLEASE
|
# - SKYVERN_AUTH_BITWARDEN_CLIENT_ID=user.your-client-id-here
|
||||||
# - BITWARDEN_MASTER_PASSWORD=FILL_ME_IN_PLEASE
|
# - SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET=your-client-secret-here
|
||||||
|
# - SKYVERN_AUTH_BITWARDEN_MASTER_PASSWORD=your-master-password-here
|
||||||
|
|
||||||
# 1Password Integration
|
# 1Password Integration
|
||||||
# If you are looking to integrate Skyvern with 1Password, you can use the following environment variables.
|
# If you are looking to integrate Skyvern with 1Password, you can use the following environment variables.
|
||||||
@@ -158,3 +159,51 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
skyvern:
|
skyvern:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
|
# uncomment for local usage of `vaultwarden` & bitwarden-cli - see more at: https://github.com/dani-garcia/vaultwarden
|
||||||
|
# First this container needs to be started and configured to sign up, create master password and organization
|
||||||
|
# Once created, under SETTINGS/SECURITY/KEYS/API you should be able to get client id and secret for CLI & Skyvern integrations
|
||||||
|
# vaultwarden:
|
||||||
|
# image: vaultwarden/server:latest-alpine
|
||||||
|
# container_name: vaultwarden
|
||||||
|
# restart: unless-stopped
|
||||||
|
# environment:
|
||||||
|
# # DOMAIN: "https://vaultwarden.example.com" # required when using a reverse proxy; your domain; vaultwarden needs to know it's https to work properly with attachments
|
||||||
|
# SIGNUPS_ALLOWED: "true" # Deactivate this with "false" after you have created your account so that no strangers can register
|
||||||
|
# volumes:
|
||||||
|
# - ~/vw-data/:/data/ # the path before the : can be changed
|
||||||
|
# ports:
|
||||||
|
# - 127.0.0.1:11002:80 # you can replace the 11002 with your preferred port
|
||||||
|
|
||||||
|
# Bitwarden CLI Server (provides REST API endpoints for Skyvern)
|
||||||
|
# Once you have master password and api credentials, you can set them below and this CLI should start providing secure access for Skyvern to Vaultwarden
|
||||||
|
# bitwarden-cli:
|
||||||
|
# build:
|
||||||
|
# context: ./bitwarden-cli-server
|
||||||
|
# dockerfile: Dockerfile
|
||||||
|
# environment:
|
||||||
|
# # Vaultwarden server URL
|
||||||
|
# BW_HOST: "http://vaultwarden"
|
||||||
|
# # API credentials for vaultwarden
|
||||||
|
# BW_CLIENTID: "user.your-client-id-here"
|
||||||
|
# BW_CLIENTSECRET: "your-client-secret-here"
|
||||||
|
# # Master password for unlocking vault
|
||||||
|
# BW_PASSWORD: "your-master-password-here"
|
||||||
|
# ports:
|
||||||
|
# # Bind to localhost only for security
|
||||||
|
# - "127.0.0.1:8002:8087"
|
||||||
|
# restart: unless-stopped
|
||||||
|
# healthcheck:
|
||||||
|
# test: [ "CMD", "curl", "-f", "http://localhost:8087/status" ]
|
||||||
|
# interval: 30s
|
||||||
|
# timeout: 10s
|
||||||
|
# retries: 5
|
||||||
|
# start_period: 30s
|
||||||
|
# depends_on:
|
||||||
|
# vaultwarden:
|
||||||
|
# condition: service_healthy
|
||||||
|
# volumes:
|
||||||
|
# # Optional: persist Bitwarden CLI config
|
||||||
|
# - ~/bitwarden-cli-config:/app/.config
|
||||||
|
# labels:
|
||||||
|
# - "traefik.enable=false" # Don't expose via reverse proxy
|
||||||
|
|||||||
@@ -40,3 +40,109 @@ Please contact sales@skyvern.com to set up the integration for this step.
|
|||||||
<img src="../images/bitwarden/bitwarden_tutorial_create_skyvern_task_block.png" />
|
<img src="../images/bitwarden/bitwarden_tutorial_create_skyvern_task_block.png" />
|
||||||
|
|
||||||
### Bitwarden Integration in Open Source
|
### Bitwarden Integration in Open Source
|
||||||
|
|
||||||
|
Skyvern can integrate with self-hosted Bitwarden-compatible services like [vaultwarden](https://github.com/dani-garcia/vaultwarden). Since vaultwarden only implements the client API (not the server endpoints), we use a Bitwarden CLI server as a bridge.
|
||||||
|
|
||||||
|
#### Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
Skyvern → bw serve (CLI Server) → vaultwarden
|
||||||
|
```
|
||||||
|
|
||||||
|
The CLI server provides the REST API endpoints that Skyvern expects, while connecting to your vaultwarden instance.
|
||||||
|
|
||||||
|
#### Quick Setup
|
||||||
|
|
||||||
|
**Step 1: Get vaultwarden API Credentials**
|
||||||
|
|
||||||
|
1. Log into your vaultwarden web interface
|
||||||
|
2. Go to **Account Settings → Security → API Key**
|
||||||
|
3. Click **View API Key**
|
||||||
|
4. Save the `client_id` and `client_secret`
|
||||||
|
|
||||||
|
**Step 2: Configure Environment Variables**
|
||||||
|
|
||||||
|
Add these to your `.env` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Skyvern Bitwarden Configuration
|
||||||
|
SKYVERN_AUTH_BITWARDEN_ORGANIZATION_ID=your-org-id-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_MASTER_PASSWORD=your-master-password-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_CLIENT_ID=user.your-client-id-here
|
||||||
|
SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET=your-client-secret-here
|
||||||
|
|
||||||
|
# Vaultwarden Configuration
|
||||||
|
BW_HOST=https://your-vaultwarden-server.com
|
||||||
|
BW_CLIENTID=${SKYVERN_AUTH_BITWARDEN_CLIENT_ID}
|
||||||
|
BW_CLIENTSECRET=${SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET}
|
||||||
|
BW_PASSWORD=${SKYVERN_AUTH_BITWARDEN_MASTER_PASSWORD}
|
||||||
|
|
||||||
|
# CLI Server Configuration (defaults are correct)
|
||||||
|
BITWARDEN_SERVER=http://localhost
|
||||||
|
BITWARDEN_SERVER_PORT=8002
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Start the Services**
|
||||||
|
|
||||||
|
The Bitwarden CLI server is included in the main Docker Compose setup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d bitwarden-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Verify Setup**
|
||||||
|
|
||||||
|
Test that the CLI server is working:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
curl http://localhost:8002/status
|
||||||
|
|
||||||
|
# List items from your vault
|
||||||
|
curl http://localhost:8002/list/object/items
|
||||||
|
```
|
||||||
|
|
||||||
|
#### How It Works
|
||||||
|
|
||||||
|
1. **vaultwarden** - Your existing password manager server
|
||||||
|
2. **bitwarden-cli container** - Runs `bw serve` to provide REST API endpoints
|
||||||
|
3. **Skyvern** - Uses the CLI server's REST API to access credentials
|
||||||
|
|
||||||
|
#### Available API Endpoints
|
||||||
|
|
||||||
|
The CLI server provides these endpoints on port 8002:
|
||||||
|
|
||||||
|
- `GET /status` - Server status
|
||||||
|
- `POST /unlock` - Unlock vault
|
||||||
|
- `GET /list/object/items` - List all items
|
||||||
|
- `GET /object/item/{id}` - Get specific item
|
||||||
|
- `POST /object/item` - Create new item
|
||||||
|
- `GET /object/template/item` - Get item template
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
|
||||||
|
**CLI Server Won't Start**
|
||||||
|
|
||||||
|
Check the container logs:
|
||||||
|
```bash
|
||||||
|
docker-compose logs bitwarden-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
Common issues:
|
||||||
|
- Invalid API credentials
|
||||||
|
- Wrong vaultwarden server URL
|
||||||
|
- Network connectivity issues
|
||||||
|
- Incorrect master password
|
||||||
|
|
||||||
|
**Skyvern Can't Connect**
|
||||||
|
|
||||||
|
1. Verify CLI server is running: `curl http://localhost:8002/status`
|
||||||
|
2. Check that `BITWARDEN_SERVER=http://localhost` and `BITWARDEN_SERVER_PORT=8002`
|
||||||
|
3. Ensure proper organization ID and credentials are set
|
||||||
|
|
||||||
|
#### Security Notes
|
||||||
|
|
||||||
|
- The CLI container runs as a non-root user
|
||||||
|
- Only binds to localhost by default for security
|
||||||
|
- Vault remains encrypted until explicitly unlocked
|
||||||
|
- Uses API key authentication with vaultwarden
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { WorkflowRunOverview } from "./routes/workflows/workflowRun/WorkflowRunO
|
|||||||
import { WorkflowRunRecording } from "./routes/workflows/workflowRun/WorkflowRunRecording";
|
import { WorkflowRunRecording } from "./routes/workflows/workflowRun/WorkflowRunRecording";
|
||||||
import { WorkflowRunCode } from "@/routes/workflows/workflowRun/WorkflowRunCode";
|
import { WorkflowRunCode } from "@/routes/workflows/workflowRun/WorkflowRunCode";
|
||||||
import { DebugStoreProvider } from "@/store/DebugStoreContext";
|
import { DebugStoreProvider } from "@/store/DebugStoreContext";
|
||||||
|
import { CredentialsPage } from "@/routes/credentials/CredentialsPage.tsx";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@@ -201,6 +202,16 @@ const router = createBrowserRouter([
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "credentials",
|
||||||
|
element: <PageLayout />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
index: true,
|
||||||
|
element: <CredentialsPage />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -56,6 +56,43 @@ function CredentialsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<CredentialsList />
|
<CredentialsList />
|
||||||
<CredentialsModal />
|
<CredentialsModal />
|
||||||
|
|
||||||
|
{/* Footer note */}
|
||||||
|
<div className="mt-8 border-t border-slate-700 pt-4">
|
||||||
|
<div className="text-sm italic text-slate-400">
|
||||||
|
<strong>Note:</strong> This feature requires a Bitwarden-compatible
|
||||||
|
server ({" "}
|
||||||
|
<a
|
||||||
|
href="https://bitwarden.com/help/self-host-an-organization/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-blue-400 underline hover:text-blue-300"
|
||||||
|
>
|
||||||
|
self-hosted Bitwarden
|
||||||
|
</a>{" "}
|
||||||
|
) or{" "}
|
||||||
|
<a
|
||||||
|
href="https://github.com/dani-garcia/vaultwarden"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-blue-400 underline hover:text-blue-300"
|
||||||
|
>
|
||||||
|
this community version
|
||||||
|
</a>{" "}
|
||||||
|
or a paid Bitwarden account. Make sure the relevant
|
||||||
|
`SKYVERN_AUTH_BITWARDEN_*` environment variables are configured. See
|
||||||
|
details{" "}
|
||||||
|
<a
|
||||||
|
href="https://docs.skyvern.com/credentials/bitwarden"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-blue-400 underline hover:text-blue-300"
|
||||||
|
>
|
||||||
|
here
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
GearIcon,
|
GearIcon,
|
||||||
LightningBoltIcon,
|
LightningBoltIcon,
|
||||||
} from "@radix-ui/react-icons";
|
} from "@radix-ui/react-icons";
|
||||||
|
import { KeyIcon } from "@/components/icons/KeyIcon.tsx";
|
||||||
|
|
||||||
function SideNav() {
|
function SideNav() {
|
||||||
const { collapsed } = useSidebarStore();
|
const { collapsed } = useSidebarStore();
|
||||||
@@ -45,6 +46,11 @@ function SideNav() {
|
|||||||
to: "/settings",
|
to: "/settings",
|
||||||
icon: <GearIcon className="size-6" />,
|
icon: <GearIcon className="size-6" />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "Credentials",
|
||||||
|
to: "/credentials",
|
||||||
|
icon: <KeyIcon className="size-6" />,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
Reference in New Issue
Block a user