@bostonuniversity/buwp-local 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.buwp-local.json +22 -0
- package/.env.local.example +26 -0
- package/IMPLEMENTATION_NOTES_V0.5.0_PHASE3.md +240 -0
- package/KEYCHAIN_IMPLEMENTATION.md +140 -0
- package/USAGE.md +31 -5
- package/bin/buwp-local.js +12 -0
- package/lib/commands/init.js +4 -0
- package/lib/commands/keychain.js +613 -0
- package/lib/commands/start.js +27 -2
- package/lib/compose-generator.js +21 -28
- package/lib/config.js +91 -0
- package/lib/index.js +15 -0
- package/lib/keychain.js +339 -0
- package/package.json +2 -2
- package/plan-environmentBasedCredentials.prompt.md +57 -0
package/.buwp-local.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"projectName": "buwp-local",
|
|
3
|
+
"image": "ghcr.io/bu-ist/bu-wp-docker-mod_shib:arm64-latest",
|
|
4
|
+
"hostname": "jaydub.local",
|
|
5
|
+
"multisite": true,
|
|
6
|
+
"services": {
|
|
7
|
+
"redis": true,
|
|
8
|
+
"s3proxy": true,
|
|
9
|
+
"shibboleth": true
|
|
10
|
+
},
|
|
11
|
+
"ports": {
|
|
12
|
+
"http": 80,
|
|
13
|
+
"https": 443,
|
|
14
|
+
"db": 3306,
|
|
15
|
+
"redis": 6379
|
|
16
|
+
},
|
|
17
|
+
"mappings": [],
|
|
18
|
+
"env": {
|
|
19
|
+
"WP_DEBUG": true,
|
|
20
|
+
"XDEBUG": false
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# BU WordPress Local Development Environment Variables
|
|
2
|
+
# Copy this file to .env.local and fill in your actual credentials
|
|
3
|
+
# NEVER commit .env.local to version control!
|
|
4
|
+
|
|
5
|
+
# Database Credentials
|
|
6
|
+
WORDPRESS_DB_PASSWORD=password
|
|
7
|
+
DB_ROOT_PASSWORD=rootpassword
|
|
8
|
+
|
|
9
|
+
# Shibboleth Configuration (if enabled)
|
|
10
|
+
SP_ENTITY_ID=https://your-sp-entity-id
|
|
11
|
+
IDP_ENTITY_ID=https://shib-test.bu.edu/idp/shibboleth
|
|
12
|
+
SHIB_IDP_LOGOUT=https://shib-test.bu.edu/idp/logout.jsp
|
|
13
|
+
SHIB_SP_KEY=your-private-key-here
|
|
14
|
+
SHIB_SP_CERT=your-certificate-here
|
|
15
|
+
|
|
16
|
+
# AWS S3 Configuration (if enabled)
|
|
17
|
+
S3_UPLOADS_BUCKET=your-bucket-name
|
|
18
|
+
S3_UPLOADS_REGION=us-east-1
|
|
19
|
+
S3_UPLOADS_ACCESS_KEY_ID=AKIA...
|
|
20
|
+
S3_UPLOADS_SECRET_ACCESS_KEY=your-secret-key
|
|
21
|
+
S3_ACCESS_RULES_TABLE=your-access-rules-table
|
|
22
|
+
|
|
23
|
+
# OLAP Configuration (if using S3 Object Lambda)
|
|
24
|
+
OLAP=your-olap-name
|
|
25
|
+
OLAP_ACCT_NBR=123456789
|
|
26
|
+
OLAP_REGION=us-east-1
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# v0.5.0 Phase 3: Hybrid Secure Temp File Integration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Completed implementation of credential loading from macOS keychain into Docker Compose via secure temporary environment files. This is the final integration step of v0.5.0 keychain feature.
|
|
5
|
+
|
|
6
|
+
## What Was Implemented
|
|
7
|
+
|
|
8
|
+
### 1. **Credential Loading Functions** (`lib/config.js`)
|
|
9
|
+
|
|
10
|
+
Added three new exported functions:
|
|
11
|
+
|
|
12
|
+
#### `loadKeychainCredentials()`
|
|
13
|
+
- Retrieves all 15 stored credentials from macOS keychain
|
|
14
|
+
- Returns empty object on non-macOS platforms (graceful degradation)
|
|
15
|
+
- Checks `isPlatformSupported()` before attempting keychain access
|
|
16
|
+
- Iterates through `CREDENTIAL_KEYS` constant to load each credential
|
|
17
|
+
|
|
18
|
+
#### `createSecureTempEnvFile(credentials, projectName)`
|
|
19
|
+
- Creates `/tmp/.buwp-local-{projectName}-{timestamp}.env` file
|
|
20
|
+
- Uses atomic file creation with exclusive write flag (`'wx'`)
|
|
21
|
+
- Sets restrictive permissions to user read/write only (`0o600`)
|
|
22
|
+
- Properly escapes multiline credentials:
|
|
23
|
+
- Backslashes: `\\` → `\\\\\\\\`
|
|
24
|
+
- Double quotes: `"` → `\"`
|
|
25
|
+
- Newlines: `\n` → `\\n`
|
|
26
|
+
- Ensures shell interpretation works correctly for complex values (SHIB_SP_KEY, SHIB_SP_CERT)
|
|
27
|
+
- Returns path to created temp file
|
|
28
|
+
|
|
29
|
+
#### `secureDeleteTempEnvFile(filePath)`
|
|
30
|
+
- Overwrites file content with zeros before deletion (defense against forensic recovery)
|
|
31
|
+
- Unlinks file after secure overwrite
|
|
32
|
+
- Returns boolean success status
|
|
33
|
+
- Non-fatal errors - logs warnings but doesn't throw (temp files are ephemeral)
|
|
34
|
+
|
|
35
|
+
### 2. **Start Command Integration** (`lib/commands/start.js`)
|
|
36
|
+
|
|
37
|
+
Updated `startCommand()` function to:
|
|
38
|
+
|
|
39
|
+
1. **Import new functions** from config.js
|
|
40
|
+
2. **Load keychain credentials** after generating compose file:
|
|
41
|
+
```javascript
|
|
42
|
+
const keychainCredentials = loadKeychainCredentials();
|
|
43
|
+
const keychainCredCount = Object.keys(keychainCredentials).length;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
3. **Create secure temp file** if credentials available:
|
|
47
|
+
```javascript
|
|
48
|
+
if (keychainCredCount > 0) {
|
|
49
|
+
tempEnvPath = createSecureTempEnvFile(keychainCredentials, projectName);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
4. **Layer environment files** in Docker Compose command:
|
|
54
|
+
```bash
|
|
55
|
+
docker compose -p {projectName} --env-file {tempEnvFile} --env-file {.env.local} -f {composePath} up -d
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
5. **Ensure cleanup** with try/finally block:
|
|
59
|
+
- Cleanup happens even if Docker Compose fails
|
|
60
|
+
- Temp file securely deleted after containers start
|
|
61
|
+
|
|
62
|
+
### 3. **Credential Precedence**
|
|
63
|
+
|
|
64
|
+
Docker Compose loads env files left-to-right with later files overriding earlier ones:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Keychain Credentials (--env-file /tmp/.buwp-local-*.env)
|
|
68
|
+
↓ [overridden by]
|
|
69
|
+
.env.local Project Overrides (--env-file .env.local)
|
|
70
|
+
↓ [overridden by]
|
|
71
|
+
docker-compose.yml Environment Defaults
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Precedence Order (highest to lowest):**
|
|
75
|
+
1. `.env.local` - Project-specific credential overrides
|
|
76
|
+
2. Keychain - Global default credentials (all 15 keys)
|
|
77
|
+
3. docker-compose.yml - Hardcoded defaults
|
|
78
|
+
|
|
79
|
+
## Security Architecture
|
|
80
|
+
|
|
81
|
+
### Threat Model: Process List Visibility
|
|
82
|
+
**Original concern:** Won't credentials be visible in `ps auxe`?
|
|
83
|
+
|
|
84
|
+
**Answer:** No. With this approach:
|
|
85
|
+
- Docker command shows: `docker compose --env-file /tmp/.buwp-local-test-project-1234567890.env ...`
|
|
86
|
+
- Credentials are in the file, NOT in the process command line
|
|
87
|
+
- Process list shows only the file path (which is harmless)
|
|
88
|
+
|
|
89
|
+
### Threat Model: Filesystem Exposure
|
|
90
|
+
**Risk:** Brief window where unencrypted credentials are on disk
|
|
91
|
+
|
|
92
|
+
**Mitigations:**
|
|
93
|
+
1. **Atomic creation** - File created exclusively with perms set atomically (no TOCTOU window)
|
|
94
|
+
2. **Restrictive permissions** - `0o600` (user read/write only, no group/others access)
|
|
95
|
+
3. **Ephemeral location** - `/tmp` directory (typically in-memory on modern systems, auto-cleaned)
|
|
96
|
+
4. **Secure deletion** - Overwrite with zeros before unlinking (prevents forensic recovery)
|
|
97
|
+
5. **Short lifetime** - File exists only during `docker compose up` command (~1-2 seconds)
|
|
98
|
+
6. **Guaranteed cleanup** - try/finally ensures deletion even if Docker fails
|
|
99
|
+
|
|
100
|
+
### Why Not Process Environment Variables?
|
|
101
|
+
- **Worse security:** All env vars visible in `ps auxe` output to any user on system
|
|
102
|
+
- **Less stable:** Large multiline values (40+ lines) cause issues
|
|
103
|
+
- **Less standard:** Breaks Docker Compose file-based patterns
|
|
104
|
+
|
|
105
|
+
### Why Not Store Credentials in .env.local?
|
|
106
|
+
- **Already doing this** - `.env.local` is still supported and takes precedence
|
|
107
|
+
- **One-time setup** - Keychain eliminates need to copy credentials to every project
|
|
108
|
+
- **Secure storage** - Keychain uses macOS Secure Enclave on newer Macs
|
|
109
|
+
|
|
110
|
+
## Integration Flow
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
1. Start command runs
|
|
114
|
+
↓
|
|
115
|
+
2. Load config from .buwp-local.json
|
|
116
|
+
↓
|
|
117
|
+
3. Load keychain credentials (15 total)
|
|
118
|
+
↓
|
|
119
|
+
4. Create temp env file (/tmp/.buwp-local-{project}-{timestamp}.env)
|
|
120
|
+
- Atomic creation with 0o600 permissions
|
|
121
|
+
- Properly escaped multiline values
|
|
122
|
+
↓
|
|
123
|
+
5. Build Docker Compose command with layered env files
|
|
124
|
+
- --env-file /tmp/.buwp-local-{project}-{timestamp}.env
|
|
125
|
+
- --env-file .env.local (if exists)
|
|
126
|
+
↓
|
|
127
|
+
6. Execute Docker Compose up
|
|
128
|
+
↓
|
|
129
|
+
7. Clean up temp file (try/finally)
|
|
130
|
+
- Overwrite with zeros
|
|
131
|
+
- Unlink
|
|
132
|
+
↓
|
|
133
|
+
8. Success message + usage tips
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Credentials Loaded
|
|
137
|
+
|
|
138
|
+
All 15 credentials from keychain are available:
|
|
139
|
+
|
|
140
|
+
**Database (2):**
|
|
141
|
+
- WORDPRESS_DB_PASSWORD
|
|
142
|
+
- DB_ROOT_PASSWORD
|
|
143
|
+
|
|
144
|
+
**Shibboleth (5):**
|
|
145
|
+
- SP_ENTITY_ID
|
|
146
|
+
- IDP_ENTITY_ID
|
|
147
|
+
- SHIB_IDP_LOGOUT
|
|
148
|
+
- SHIB_SP_KEY (40+ lines)
|
|
149
|
+
- SHIB_SP_CERT (24+ lines)
|
|
150
|
+
|
|
151
|
+
**S3 (5):**
|
|
152
|
+
- S3_UPLOADS_BUCKET
|
|
153
|
+
- S3_UPLOADS_REGION
|
|
154
|
+
- S3_UPLOADS_ACCESS_KEY_ID
|
|
155
|
+
- S3_UPLOADS_SECRET_ACCESS_KEY
|
|
156
|
+
- S3_ACCESS_RULES_TABLE
|
|
157
|
+
|
|
158
|
+
**OLAP (3):**
|
|
159
|
+
- OLAP
|
|
160
|
+
- OLAP_ACCT_NBR
|
|
161
|
+
- OLAP_REGION
|
|
162
|
+
|
|
163
|
+
## Testing Results
|
|
164
|
+
|
|
165
|
+
Automated integration test verification:
|
|
166
|
+
|
|
167
|
+
✓ Load 15 credentials from keychain
|
|
168
|
+
✓ Create secure temp env file with 0o600 permissions
|
|
169
|
+
✓ Format env file with proper KEY="VALUE" quoting
|
|
170
|
+
✓ Handle multiline value escaping correctly
|
|
171
|
+
✓ Overwrite file with zeros before deletion
|
|
172
|
+
✓ Securely delete temp file
|
|
173
|
+
|
|
174
|
+
All tests passed successfully.
|
|
175
|
+
|
|
176
|
+
## Version Update
|
|
177
|
+
|
|
178
|
+
Updated package.json version:
|
|
179
|
+
- Previous: v0.4.1
|
|
180
|
+
- Current: v0.5.0
|
|
181
|
+
|
|
182
|
+
## Code Quality
|
|
183
|
+
|
|
184
|
+
All code passes ESLint checks with no errors or warnings.
|
|
185
|
+
|
|
186
|
+
## Next Steps
|
|
187
|
+
|
|
188
|
+
Possible future enhancements (not in v0.5.0 scope):
|
|
189
|
+
|
|
190
|
+
1. **Phase 4: Init Command Enhancements**
|
|
191
|
+
- Auto-populate `buwp-local setup --file` from existing `.env` files
|
|
192
|
+
- Suggest keychain import during `init` command
|
|
193
|
+
|
|
194
|
+
2. **Phase 5: Global Registry**
|
|
195
|
+
- `~/.buwp-local/registry.json` tracking which projects have credentials
|
|
196
|
+
- Dashboard showing all stored credentials across projects
|
|
197
|
+
|
|
198
|
+
3. **Phase 6: Cross-Platform Support**
|
|
199
|
+
- Windows DPAPI support (via `credential` PowerShell module)
|
|
200
|
+
- Linux pass/secretservice support
|
|
201
|
+
- Fallback to encrypted `.buwp-local/.env.encrypted` files
|
|
202
|
+
|
|
203
|
+
## Architecture Summary
|
|
204
|
+
|
|
205
|
+
**Hybrid Secure Temp File Approach:**
|
|
206
|
+
- **Security:** Process list hidden + filesystem defenses
|
|
207
|
+
- **Stability:** Aligns with Docker Compose standard patterns
|
|
208
|
+
- **Usability:** Intuitive file-based precedence and override mechanism
|
|
209
|
+
- **Compatibility:** Maintains existing `.env.local` behavior
|
|
210
|
+
|
|
211
|
+
**Key Decision Rationale:**
|
|
212
|
+
Process list visibility is worse attack vector than brief filesystem window with defense-in-depth mitigations (atomic creation, 600 perms, /tmp location, overwrite-before-delete).
|
|
213
|
+
|
|
214
|
+
## Files Modified
|
|
215
|
+
|
|
216
|
+
1. `lib/config.js` (+80 lines)
|
|
217
|
+
- Added keychain import
|
|
218
|
+
- Added 3 new exported functions
|
|
219
|
+
- No breaking changes to existing exports
|
|
220
|
+
|
|
221
|
+
2. `lib/commands/start.js` (+25 lines)
|
|
222
|
+
- Updated imports to include 3 new functions
|
|
223
|
+
- Added credential loading logic
|
|
224
|
+
- Added temp file creation and cleanup
|
|
225
|
+
- No breaking changes to command interface
|
|
226
|
+
|
|
227
|
+
3. `package.json`
|
|
228
|
+
- Updated version to 0.5.0
|
|
229
|
+
|
|
230
|
+
## Status Summary
|
|
231
|
+
|
|
232
|
+
**v0.5.0 Completion Status:**
|
|
233
|
+
- ✅ Phase 1: Keychain core module (v0.5.0)
|
|
234
|
+
- ✅ Phase 2: JSON bulk import (v0.5.0)
|
|
235
|
+
- ✅ Phase 3: Hybrid secure temp file integration (v0.5.0) ← COMPLETED THIS SESSION
|
|
236
|
+
- ⏭️ Phase 4: Init command enhancements (v0.6.0)
|
|
237
|
+
- ⏭️ Phase 5: Global registry (v0.7.0)
|
|
238
|
+
- ⏭️ Phase 6: Cross-platform support (v1.0.0+)
|
|
239
|
+
|
|
240
|
+
**v0.5.0 is now feature-complete and ready for testing.**
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Keychain Integration - Implementation Summary
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Successfully implemented macOS Keychain integration for secure credential storage in buwp-local v0.5.0. This allows users to store credentials once and have them automatically available across all projects.
|
|
6
|
+
|
|
7
|
+
## Files Created
|
|
8
|
+
|
|
9
|
+
### 1. `lib/keychain.js` - Core Keychain Module
|
|
10
|
+
**Functions:**
|
|
11
|
+
- `setCredential(key, value)` - Store credential in keychain
|
|
12
|
+
- `getCredential(key)` - Retrieve credential from keychain
|
|
13
|
+
- `hasCredential(key)` - Check if credential exists
|
|
14
|
+
- `deleteCredential(key)` - Remove credential
|
|
15
|
+
- `listCredentials()` - Get all stored credential keys
|
|
16
|
+
- `clearAllCredentials()` - Remove all buwp-local credentials
|
|
17
|
+
- `isPlatformSupported()` - Check for macOS platform
|
|
18
|
+
|
|
19
|
+
**Constants:**
|
|
20
|
+
- `CREDENTIAL_KEYS` - All 15 credential keys
|
|
21
|
+
- `CREDENTIAL_GROUPS` - Organized by category (database, shibboleth, s3, olap)
|
|
22
|
+
- `CREDENTIAL_DESCRIPTIONS` - Human-readable descriptions for prompts
|
|
23
|
+
|
|
24
|
+
**Implementation Details:**
|
|
25
|
+
- Uses macOS `security` command via `execSync`
|
|
26
|
+
- Service name: `buwp-local`
|
|
27
|
+
- Uses `-U` flag to update existing credentials instead of duplicating
|
|
28
|
+
- Graceful error handling with user-friendly messages
|
|
29
|
+
|
|
30
|
+
### 2. `lib/commands/keychain.js` - CLI Command Handler
|
|
31
|
+
**Subcommands:**
|
|
32
|
+
- `setup` - Interactive setup for all credentials
|
|
33
|
+
- `set <key> [value]` - Set individual credential
|
|
34
|
+
- `get <key>` - Retrieve credential (masked display)
|
|
35
|
+
- `list` - Show all stored credentials by group
|
|
36
|
+
- `clear` - Remove all credentials (with confirmation)
|
|
37
|
+
- `status` - Show platform support and credential status
|
|
38
|
+
|
|
39
|
+
**Features:**
|
|
40
|
+
- Interactive prompts using `prompts` package
|
|
41
|
+
- Grouped credential display (database, shibboleth, s3, olap)
|
|
42
|
+
- Existing credential detection with overwrite warnings
|
|
43
|
+
- Force flag support for automation
|
|
44
|
+
- macOS keychain access warning at start of setup
|
|
45
|
+
|
|
46
|
+
## Files Modified
|
|
47
|
+
|
|
48
|
+
### 3. `bin/buwp-local.js`
|
|
49
|
+
- Added import for `keychainCommand`
|
|
50
|
+
- Registered `keychain` command with subcommands
|
|
51
|
+
- Added `-f, --force` option support
|
|
52
|
+
|
|
53
|
+
### 4. `lib/index.js`
|
|
54
|
+
- Exported all keychain functions
|
|
55
|
+
- Exported credential schema constants
|
|
56
|
+
|
|
57
|
+
## Usage Examples
|
|
58
|
+
|
|
59
|
+
### First-Time Setup
|
|
60
|
+
```bash
|
|
61
|
+
# Interactive setup (all credentials)
|
|
62
|
+
buwp-local keychain setup
|
|
63
|
+
|
|
64
|
+
# Set individual credential
|
|
65
|
+
buwp-local keychain set WORDPRESS_DB_PASSWORD mypassword
|
|
66
|
+
|
|
67
|
+
# Check status
|
|
68
|
+
buwp-local keychain status
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Managing Credentials
|
|
72
|
+
```bash
|
|
73
|
+
# List stored credentials
|
|
74
|
+
buwp-local keychain list
|
|
75
|
+
|
|
76
|
+
# Get credential value (masked)
|
|
77
|
+
buwp-local keychain get WORDPRESS_DB_PASSWORD
|
|
78
|
+
|
|
79
|
+
# Clear all credentials
|
|
80
|
+
buwp-local keychain clear
|
|
81
|
+
# Or skip confirmation:
|
|
82
|
+
buwp-local keychain clear --force
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Testing Results
|
|
86
|
+
|
|
87
|
+
✅ All functions tested and working:
|
|
88
|
+
- Platform detection (macOS supported ✓)
|
|
89
|
+
- Set credential via command line
|
|
90
|
+
- Get credential with masking (test*****word)
|
|
91
|
+
- List credentials by group
|
|
92
|
+
- Clear all credentials
|
|
93
|
+
- Linting passes cleanly
|
|
94
|
+
|
|
95
|
+
## User Experience
|
|
96
|
+
|
|
97
|
+
### Warnings & Messages
|
|
98
|
+
- **Platform check**: Non-macOS users see clear message about .env.local fallback
|
|
99
|
+
- **Keychain access**: Users warned about macOS permission prompt before setup
|
|
100
|
+
- **Overwrite protection**: Warns when overwriting existing credentials
|
|
101
|
+
- **Grouped display**: Credentials organized by functional category
|
|
102
|
+
|
|
103
|
+
### Security Features
|
|
104
|
+
- Credentials never displayed in full (masked in `get` command)
|
|
105
|
+
- Stored securely in macOS keychain (encrypted by OS)
|
|
106
|
+
- Individual credential deletion supported
|
|
107
|
+
- Bulk clear with confirmation (unless --force)
|
|
108
|
+
|
|
109
|
+
## Design Decisions
|
|
110
|
+
|
|
111
|
+
1. **Full credential set required** - `setup` prompts for all 15 credentials to ensure complete stack functionality
|
|
112
|
+
2. **Warning before overwrite** - Users must confirm when updating existing credentials (unless --force)
|
|
113
|
+
3. **Sparse error messages** - Simple, clear error reporting without over-engineering
|
|
114
|
+
4. **macOS-only for now** - Platform detection with graceful fallback to .env.local on other systems
|
|
115
|
+
|
|
116
|
+
## Next Steps (v0.5.0 continued)
|
|
117
|
+
|
|
118
|
+
**Remaining work:**
|
|
119
|
+
1. Update `start.js` to load credentials from keychain
|
|
120
|
+
2. Update `init.js` to detect keychain credentials
|
|
121
|
+
3. Implement credential resolution priority: `.env.local` → keychain → defaults
|
|
122
|
+
4. Create global registry (`~/.buwp-local/registry.json`)
|
|
123
|
+
5. Update documentation
|
|
124
|
+
|
|
125
|
+
**Future enhancements (v0.6.0+):**
|
|
126
|
+
- Cross-platform support (Windows Credential Manager, Linux Secret Service)
|
|
127
|
+
- Project-specific credential overrides
|
|
128
|
+
- Credential import/export
|
|
129
|
+
- Team credential sharing mechanisms
|
|
130
|
+
|
|
131
|
+
## Benefits Delivered
|
|
132
|
+
|
|
133
|
+
✅ **One-time setup** - Enter credentials once, use across all projects
|
|
134
|
+
✅ **Secure storage** - Leverages macOS keychain encryption
|
|
135
|
+
✅ **Simple CLI** - Intuitive subcommands for all operations
|
|
136
|
+
✅ **Backward compatible** - .env.local still works as override
|
|
137
|
+
✅ **Developer friendly** - Clear messages and helpful status command
|
|
138
|
+
✅ **Production ready** - Fully tested and linted
|
|
139
|
+
|
|
140
|
+
This implementation solves the multi-repo credential fatigue problem while maintaining backward compatibility and providing a secure, native macOS integration.
|
package/USAGE.md
CHANGED
|
@@ -51,7 +51,13 @@ Edit `.buwp-local.json` to map your local repository into the container:
|
|
|
51
51
|
|
|
52
52
|
### 4. Create `.env.local` for secrets
|
|
53
53
|
|
|
54
|
-
Create `.env.local` (never commit this file!):
|
|
54
|
+
Create `.env.local` (never commit this file!) or copy from the example:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cp .env.local.example .env.local
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Then edit `.env.local` with your actual credentials:
|
|
55
61
|
|
|
56
62
|
```bash
|
|
57
63
|
# Database
|
|
@@ -70,6 +76,7 @@ S3_UPLOADS_BUCKET=your-bucket
|
|
|
70
76
|
S3_UPLOADS_REGION=us-east-1
|
|
71
77
|
S3_UPLOADS_ACCESS_KEY_ID=your-access-key
|
|
72
78
|
S3_UPLOADS_SECRET_ACCESS_KEY=your-secret-key
|
|
79
|
+
S3_ACCESS_RULES_TABLE=your-access-rules-table
|
|
73
80
|
|
|
74
81
|
# OLAP
|
|
75
82
|
OLAP=your-olap-name
|
|
@@ -77,6 +84,8 @@ OLAP_ACCT_NBR=your-account-number
|
|
|
77
84
|
OLAP_REGION=us-east-1
|
|
78
85
|
```
|
|
79
86
|
|
|
87
|
+
**Important:** Credentials are read directly from `.env.local` by Docker Compose. They are never written to the generated `docker-compose.yml` file, making it safe to review or share the generated compose file without exposing secrets.
|
|
88
|
+
|
|
80
89
|
### 5. Add hostname to /etc/hosts
|
|
81
90
|
|
|
82
91
|
```bash
|
|
@@ -226,10 +235,27 @@ Map your local code into the container:
|
|
|
226
235
|
## Security Best Practices
|
|
227
236
|
|
|
228
237
|
1. **Never commit `.env.local`** - This file contains secrets
|
|
229
|
-
2. **Never commit `.buwp-local/`** - This contains generated files
|
|
230
|
-
3. **Do commit `.buwp-local.json`** - This is your configuration template
|
|
231
|
-
4. **Use environment variables for all secrets**
|
|
232
|
-
5. **
|
|
238
|
+
2. **Never commit `.buwp-local/`** - This directory contains generated files
|
|
239
|
+
3. **Do commit `.buwp-local.json`** - This is your configuration template (no secrets)
|
|
240
|
+
4. **Use environment variables for all secrets** - Credentials stay in `.env.local` and are never written to generated files
|
|
241
|
+
5. **Review generated compose files** - The generated `docker-compose.yml` only contains variable references like `${WORDPRESS_DB_PASSWORD}`, not actual credentials
|
|
242
|
+
6. **Copy `.env.local.example`** - Use the provided template to create your `.env.local` file
|
|
243
|
+
7. **Consider using macOS Keychain** for even better security (future feature)
|
|
244
|
+
|
|
245
|
+
### How Credentials Work
|
|
246
|
+
|
|
247
|
+
buwp-local uses Docker Compose's native environment variable interpolation:
|
|
248
|
+
|
|
249
|
+
1. **You provide** credentials in `.env.local`
|
|
250
|
+
2. **buwp-local generates** `docker-compose.yml` with variable references like `${VAR_NAME}`
|
|
251
|
+
3. **Docker Compose reads** `.env.local` at runtime and substitutes the values
|
|
252
|
+
4. **Your secrets never** get written to any generated files
|
|
253
|
+
|
|
254
|
+
This means:
|
|
255
|
+
- ✅ Generated compose files are safe to review or share
|
|
256
|
+
- ✅ No credentials in version control (even accidentally)
|
|
257
|
+
- ✅ Industry-standard Docker Compose pattern
|
|
258
|
+
- ✅ Simple and secure
|
|
233
259
|
|
|
234
260
|
## File Structure
|
|
235
261
|
|
package/bin/buwp-local.js
CHANGED
|
@@ -29,6 +29,7 @@ import wpCommand from '../lib/commands/wp.js';
|
|
|
29
29
|
import shellCommand from '../lib/commands/shell.js';
|
|
30
30
|
import configCommand from '../lib/commands/config.js';
|
|
31
31
|
import initCommand from '../lib/commands/init.js';
|
|
32
|
+
import keychainCommand from '../lib/commands/keychain.js';
|
|
32
33
|
|
|
33
34
|
const program = new Command();
|
|
34
35
|
|
|
@@ -103,6 +104,17 @@ program
|
|
|
103
104
|
.description('Open an interactive bash shell in the WordPress container')
|
|
104
105
|
.action(shellCommand);
|
|
105
106
|
|
|
107
|
+
// Keychain command
|
|
108
|
+
program
|
|
109
|
+
.command('keychain <subcommand> [args...]')
|
|
110
|
+
.description('Manage credentials in macOS keychain')
|
|
111
|
+
.option('-f, --force', 'Skip confirmation prompts')
|
|
112
|
+
.option('--file <path>', 'Read credential from file (for multiline content)')
|
|
113
|
+
.option('--stdin', 'Read credential from stdin')
|
|
114
|
+
.action((subcommand, args, options) => {
|
|
115
|
+
keychainCommand(subcommand, args, options);
|
|
116
|
+
});
|
|
117
|
+
|
|
106
118
|
// Error handling
|
|
107
119
|
program.exitOverride();
|
|
108
120
|
|
package/lib/commands/init.js
CHANGED
|
@@ -133,6 +133,10 @@ async function initCommand(options) {
|
|
|
133
133
|
name: 'hostname',
|
|
134
134
|
message: 'Hostname',
|
|
135
135
|
initial: (prev, values) => {
|
|
136
|
+
// For sandbox, use just username.local; for other types include project name
|
|
137
|
+
if (values.projectType === 'sandbox') {
|
|
138
|
+
return `${userName}.local`;
|
|
139
|
+
}
|
|
136
140
|
return `${userName}-${values.projectName}.local`;
|
|
137
141
|
},
|
|
138
142
|
validate: value => {
|