@northbridge-security/secureai 0.1.13
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/.claude/README.md +122 -0
- package/.claude/commands/architect/clean.md +978 -0
- package/.claude/commands/architect/kiss.md +762 -0
- package/.claude/commands/architect/review.md +704 -0
- package/.claude/commands/catchup.md +90 -0
- package/.claude/commands/code.md +115 -0
- package/.claude/commands/commit.md +1218 -0
- package/.claude/commands/cover.md +1298 -0
- package/.claude/commands/fmea.md +275 -0
- package/.claude/commands/kaizen.md +312 -0
- package/.claude/commands/pr.md +503 -0
- package/.claude/commands/todo.md +99 -0
- package/.claude/commands/worktree.md +738 -0
- package/.claude/commands/wrapup.md +103 -0
- package/LICENSE +183 -0
- package/README.md +108 -0
- package/dist/cli.js +75634 -0
- package/docs/agents/devops-reviewer.md +889 -0
- package/docs/agents/kiss-simplifier.md +1088 -0
- package/docs/agents/typescript.md +8 -0
- package/docs/guides/README.md +109 -0
- package/docs/guides/agents.clean.arch.md +244 -0
- package/docs/guides/agents.clean.arch.ts.md +1314 -0
- package/docs/guides/agents.gotask.md +1037 -0
- package/docs/guides/agents.markdown.md +1209 -0
- package/docs/guides/agents.onepassword.md +285 -0
- package/docs/guides/agents.sonar.md +857 -0
- package/docs/guides/agents.tdd.md +838 -0
- package/docs/guides/agents.tdd.ts.md +1062 -0
- package/docs/guides/agents.typesript.md +1389 -0
- package/docs/guides/github-mcp.md +1075 -0
- package/package.json +130 -0
- package/packages/secureai-cli/src/cli.ts +21 -0
- package/tasks/README.md +880 -0
- package/tasks/aws.yml +64 -0
- package/tasks/bash.yml +118 -0
- package/tasks/bun.yml +738 -0
- package/tasks/claude.yml +183 -0
- package/tasks/docker.yml +420 -0
- package/tasks/docs.yml +127 -0
- package/tasks/git.yml +1336 -0
- package/tasks/gotask.yml +132 -0
- package/tasks/json.yml +77 -0
- package/tasks/markdown.yml +95 -0
- package/tasks/onepassword.yml +350 -0
- package/tasks/security.yml +102 -0
- package/tasks/sonar.yml +437 -0
- package/tasks/template.yml +74 -0
- package/tasks/vscode.yml +103 -0
- package/tasks/yaml.yml +121 -0
package/tasks/claude.yml
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Claude Code & MCP Task Library
|
|
2
|
+
# Tasks for managing Claude Code integration and MCP servers
|
|
3
|
+
|
|
4
|
+
version: "3"
|
|
5
|
+
|
|
6
|
+
tasks:
|
|
7
|
+
default:
|
|
8
|
+
desc: "Show available Claude Code tasks"
|
|
9
|
+
aliases: [help, h]
|
|
10
|
+
silent: true
|
|
11
|
+
cmds:
|
|
12
|
+
- |
|
|
13
|
+
# Color codes
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
YELLOW='\033[0;33m'
|
|
16
|
+
BOLD='\033[1m'
|
|
17
|
+
NC='\033[0m'
|
|
18
|
+
|
|
19
|
+
echo -e "${BOLD}Claude Code & MCP Operations${NC}"
|
|
20
|
+
echo ""
|
|
21
|
+
echo "Command Alias Description Examples"
|
|
22
|
+
echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
|
|
23
|
+
echo -e "${BOLD}Settings Management:${NC}"
|
|
24
|
+
echo -e " ${GREEN}task claude:settings:open${NC} ${YELLOW}so${NC} Open Claude settings.json in IDE"
|
|
25
|
+
echo -e " ${GREEN}task claude:settings:show${NC} ${YELLOW}ss${NC} Show current Claude settings"
|
|
26
|
+
echo -e " ${GREEN}task claude:settings:path${NC} ${YELLOW}sp${NC} Print Claude settings file path"
|
|
27
|
+
echo ""
|
|
28
|
+
echo -e "${BOLD}MCP Server Management:${NC}"
|
|
29
|
+
echo -e " ${GREEN}task claude:mcp:install${NC} ${YELLOW}mi${NC} Install MCP server globally"
|
|
30
|
+
echo -e " ${GREEN}task claude:mcp:verify${NC} ${YELLOW}mv${NC} Verify MCP server installation"
|
|
31
|
+
echo -e " ${GREEN}task claude:mcp:status${NC} ${YELLOW}ms${NC} Show MCP server status"
|
|
32
|
+
echo -e " ${GREEN}task claude:mcp:remove${NC} ${YELLOW}mr${NC} Remove MCP server"
|
|
33
|
+
echo ""
|
|
34
|
+
echo -e "${BOLD}Installer Testing:${NC}"
|
|
35
|
+
echo -e " ${GREEN}task claude:installer:test${NC} ${YELLOW}it${NC} Run complete installer test suite"
|
|
36
|
+
echo -e " ${GREEN}task claude:installer:test:force${NC} ${YELLOW}itf${NC} Test force reinstall"
|
|
37
|
+
echo -e " ${GREEN}task claude:installer:test:clean${NC} ${YELLOW}itc${NC} Clean up test installations"
|
|
38
|
+
|
|
39
|
+
mcp:install:
|
|
40
|
+
desc: Install MCP server globally
|
|
41
|
+
aliases: [mi]
|
|
42
|
+
silent: true
|
|
43
|
+
cmds:
|
|
44
|
+
- |
|
|
45
|
+
# Source secrets if .env has 1Password references
|
|
46
|
+
if [ -f .env ] && grep -q "op://" .env 2>/dev/null; then
|
|
47
|
+
TEMP_ENV=$(task op:export)
|
|
48
|
+
source "$TEMP_ENV"
|
|
49
|
+
fi
|
|
50
|
+
bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-install.ts
|
|
51
|
+
|
|
52
|
+
mcp:verify:
|
|
53
|
+
desc: Verify MCP server installation
|
|
54
|
+
aliases: [mv]
|
|
55
|
+
silent: true
|
|
56
|
+
cmds:
|
|
57
|
+
- bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-verify.ts
|
|
58
|
+
|
|
59
|
+
mcp:remove:
|
|
60
|
+
desc: Remove MCP server
|
|
61
|
+
aliases: [mr]
|
|
62
|
+
silent: true
|
|
63
|
+
cmds:
|
|
64
|
+
- bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-remove.ts
|
|
65
|
+
|
|
66
|
+
mcp:status:
|
|
67
|
+
desc: Show MCP server status
|
|
68
|
+
aliases: [ms]
|
|
69
|
+
silent: true
|
|
70
|
+
cmds:
|
|
71
|
+
- bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-status.ts
|
|
72
|
+
|
|
73
|
+
installer:test:
|
|
74
|
+
desc: Run complete installer test suite
|
|
75
|
+
aliases: [it]
|
|
76
|
+
silent: true
|
|
77
|
+
cmds:
|
|
78
|
+
- bun run {{.TASKFILE_DIR}}/../src/tasks/claude/test-installer.ts
|
|
79
|
+
|
|
80
|
+
installer:test:force:
|
|
81
|
+
desc: Test force reinstall
|
|
82
|
+
aliases: [itf]
|
|
83
|
+
silent: true
|
|
84
|
+
cmds:
|
|
85
|
+
- bun run {{.TASKFILE_DIR}}/../src/tasks/claude/test-installer.ts --force
|
|
86
|
+
|
|
87
|
+
installer:test:clean:
|
|
88
|
+
desc: Clean up test installations
|
|
89
|
+
aliases: [itc]
|
|
90
|
+
silent: true
|
|
91
|
+
cmds:
|
|
92
|
+
- bun run {{.TASKFILE_DIR}}/../src/tasks/claude/clean-test.ts
|
|
93
|
+
|
|
94
|
+
# Settings Management
|
|
95
|
+
settings:open:
|
|
96
|
+
desc: Open Claude settings.json in detected IDE
|
|
97
|
+
aliases: [so]
|
|
98
|
+
silent: true
|
|
99
|
+
cmds:
|
|
100
|
+
- |
|
|
101
|
+
# Get Claude settings path (cross-platform)
|
|
102
|
+
case "$(uname -s)" in
|
|
103
|
+
Darwin|Linux)
|
|
104
|
+
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
105
|
+
;;
|
|
106
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
107
|
+
SETTINGS_PATH="$USERPROFILE/.claude/settings.json"
|
|
108
|
+
;;
|
|
109
|
+
*)
|
|
110
|
+
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
111
|
+
;;
|
|
112
|
+
esac
|
|
113
|
+
|
|
114
|
+
# Create settings file if it doesn't exist
|
|
115
|
+
if [ ! -f "$SETTINGS_PATH" ]; then
|
|
116
|
+
mkdir -p "$(dirname "$SETTINGS_PATH")"
|
|
117
|
+
echo '{}' > "$SETTINGS_PATH"
|
|
118
|
+
echo "Created new settings file: $SETTINGS_PATH"
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# Use core ide:open utility
|
|
122
|
+
task ide:open FILE="$SETTINGS_PATH"
|
|
123
|
+
|
|
124
|
+
settings:show:
|
|
125
|
+
desc: Show current Claude settings
|
|
126
|
+
aliases: [ss]
|
|
127
|
+
silent: true
|
|
128
|
+
cmds:
|
|
129
|
+
- |
|
|
130
|
+
GREEN='\033[0;32m'
|
|
131
|
+
YELLOW='\033[0;33m'
|
|
132
|
+
CYAN='\033[0;36m'
|
|
133
|
+
BOLD='\033[1m'
|
|
134
|
+
NC='\033[0m'
|
|
135
|
+
|
|
136
|
+
# Get Claude settings path (cross-platform)
|
|
137
|
+
case "$(uname -s)" in
|
|
138
|
+
Darwin|Linux)
|
|
139
|
+
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
140
|
+
;;
|
|
141
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
142
|
+
SETTINGS_PATH="$USERPROFILE/.claude/settings.json"
|
|
143
|
+
;;
|
|
144
|
+
*)
|
|
145
|
+
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
146
|
+
;;
|
|
147
|
+
esac
|
|
148
|
+
|
|
149
|
+
echo -e "${BOLD}Claude Settings${NC}"
|
|
150
|
+
echo -e "${CYAN}Path:${NC} $SETTINGS_PATH"
|
|
151
|
+
echo ""
|
|
152
|
+
|
|
153
|
+
if [ -f "$SETTINGS_PATH" ]; then
|
|
154
|
+
# Pretty print JSON with jq if available, otherwise cat
|
|
155
|
+
if command -v jq &> /dev/null; then
|
|
156
|
+
jq '.' "$SETTINGS_PATH"
|
|
157
|
+
else
|
|
158
|
+
cat "$SETTINGS_PATH"
|
|
159
|
+
fi
|
|
160
|
+
else
|
|
161
|
+
echo -e "${YELLOW}Settings file does not exist${NC}"
|
|
162
|
+
echo "Run 'task claude:settings:open' to create it"
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
settings:path:
|
|
166
|
+
desc: Print Claude settings file path
|
|
167
|
+
aliases: [sp]
|
|
168
|
+
silent: true
|
|
169
|
+
cmds:
|
|
170
|
+
- |
|
|
171
|
+
# Get Claude settings path (cross-platform)
|
|
172
|
+
case "$(uname -s)" in
|
|
173
|
+
Darwin|Linux)
|
|
174
|
+
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
175
|
+
;;
|
|
176
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
177
|
+
SETTINGS_PATH="$USERPROFILE/.claude/settings.json"
|
|
178
|
+
;;
|
|
179
|
+
*)
|
|
180
|
+
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
181
|
+
;;
|
|
182
|
+
esac
|
|
183
|
+
echo "$SETTINGS_PATH"
|
package/tasks/docker.yml
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
version: "3"
|
|
2
|
+
|
|
3
|
+
vars:
|
|
4
|
+
CONTAINER_NAME: ai-toolkit-linux-debug
|
|
5
|
+
COMPOSE_FILE: docker/linux-debug/docker-compose.yml
|
|
6
|
+
DOCKER_SOCKET: /var/run/docker.sock
|
|
7
|
+
TRIVY_IMAGE: aquasec/trivy:latest
|
|
8
|
+
DEFAULT_SEVERITY: HIGH,CRITICAL
|
|
9
|
+
|
|
10
|
+
includes:
|
|
11
|
+
linux:
|
|
12
|
+
taskfile: ../docker/linux-debug/linux.yml
|
|
13
|
+
dir: docker/linux-debug
|
|
14
|
+
|
|
15
|
+
tasks:
|
|
16
|
+
default:
|
|
17
|
+
desc: "Show available Docker tasks"
|
|
18
|
+
silent: true
|
|
19
|
+
cmds:
|
|
20
|
+
- |
|
|
21
|
+
GREEN='\033[0;32m'
|
|
22
|
+
YELLOW='\033[0;33m'
|
|
23
|
+
BOLD='\033[1m'
|
|
24
|
+
NC='\033[0m'
|
|
25
|
+
|
|
26
|
+
echo -e "${BOLD}Docker Environment Tasks${NC}"
|
|
27
|
+
echo ""
|
|
28
|
+
echo "Command Alias Description Example"
|
|
29
|
+
echo "─────────────────────────────────────────────────────────────────────────────────────-----------------------------"
|
|
30
|
+
|
|
31
|
+
- task: linux:help:info
|
|
32
|
+
|
|
33
|
+
- |
|
|
34
|
+
GREEN='\033[0;32m'
|
|
35
|
+
YELLOW='\033[0;33m'
|
|
36
|
+
BOLD='\033[1m'
|
|
37
|
+
NC='\033[0m'
|
|
38
|
+
echo ""
|
|
39
|
+
echo -e "${BOLD}Image Operations:${NC}"
|
|
40
|
+
echo -e " ${GREEN}task docker:build${NC} Build with buildx (multi-arch) IMAGE=... PATH=... [PUSH=true]"
|
|
41
|
+
echo -e " ${GREEN}task docker:tag${NC} Tag Docker image SOURCE=... TARGET=..."
|
|
42
|
+
echo -e " ${GREEN}task docker:push${NC} Push image to registry IMAGE=... TAG=..."
|
|
43
|
+
echo ""
|
|
44
|
+
echo -e "${BOLD}GitHub Container Registry:${NC}"
|
|
45
|
+
echo -e " ${GREEN}task docker:git:login${NC} Login to ghcr.io USER=... TOKEN=..."
|
|
46
|
+
echo -e " ${GREEN}task docker:git:push${NC} Push to ghcr.io IMAGE=... TAG=... USER=..."
|
|
47
|
+
echo ""
|
|
48
|
+
echo -e "${BOLD}Security Scanning:${NC}"
|
|
49
|
+
echo -e " ${GREEN}task docker:scan${NC} Scan image or Dockerfile IMAGE=... or FILE=..."
|
|
50
|
+
echo -e " ${GREEN}task docker:scan:init${NC} Initialize Trivy cache"
|
|
51
|
+
echo ""
|
|
52
|
+
echo -e "${BOLD}Examples:${NC}"
|
|
53
|
+
echo -e " # Test with local code (recommended)"
|
|
54
|
+
echo -e " task docker:linux:build && task docker:linux:test"
|
|
55
|
+
echo ""
|
|
56
|
+
echo -e " # Interactive debugging with SSH"
|
|
57
|
+
echo -e " task docker:linux:up"
|
|
58
|
+
echo -e " ssh -p 2222 developer@localhost"
|
|
59
|
+
echo -e " task docker:linux:down"
|
|
60
|
+
echo ""
|
|
61
|
+
echo -e " # Scan existing image by name"
|
|
62
|
+
echo -e " task docker:scan IMAGE=myapp TAG=v1.0.0"
|
|
63
|
+
echo ""
|
|
64
|
+
echo -e " # Build from Dockerfile and scan (config + vulnerabilities)"
|
|
65
|
+
echo -e " task docker:scan FILE=Dockerfile"
|
|
66
|
+
echo -e " task docker:scan FILE=/absolute/path/to/Dockerfile"
|
|
67
|
+
echo ""
|
|
68
|
+
echo -e " # Build and push Docker image"
|
|
69
|
+
echo -e " task docker:build IMAGE=myapp TAG=v1.0.0 PATH=."
|
|
70
|
+
echo -e " task docker:git:push IMAGE=myapp TAG=v1.0.0 USER=username TOKEN=ghp_xxx"
|
|
71
|
+
|
|
72
|
+
# Build Docker image with buildx (multi-arch support)
|
|
73
|
+
build:
|
|
74
|
+
desc: "Build Docker image with buildx (multi-arch)"
|
|
75
|
+
silent: true
|
|
76
|
+
vars:
|
|
77
|
+
IMAGE_NAME: '{{.IMAGE | default ""}}'
|
|
78
|
+
IMAGE_TAG: '{{.TAG | default "latest"}}'
|
|
79
|
+
DOCKER_PATH: '{{.PATH | default "."}}'
|
|
80
|
+
DOCKERFILE: '{{.FILE | default "Dockerfile"}}'
|
|
81
|
+
PLATFORM: '{{.PLATFORM | default "linux/amd64,linux/arm64"}}'
|
|
82
|
+
PUSH_FLAG: '{{if eq .PUSH "true"}}--push{{else}}--load{{end}}'
|
|
83
|
+
cmds:
|
|
84
|
+
- |
|
|
85
|
+
GREEN='\033[0;32m'
|
|
86
|
+
RED='\033[0;31m'
|
|
87
|
+
YELLOW='\033[0;33m'
|
|
88
|
+
NC='\033[0m'
|
|
89
|
+
|
|
90
|
+
IMAGE="{{.IMAGE_NAME}}"
|
|
91
|
+
TAG="{{.IMAGE_TAG}}"
|
|
92
|
+
CONTEXT="{{.DOCKER_PATH}}"
|
|
93
|
+
DOCKERFILE="{{.DOCKERFILE}}"
|
|
94
|
+
PLATFORM="{{.PLATFORM}}"
|
|
95
|
+
PUSH="{{.PUSH_FLAG}}"
|
|
96
|
+
|
|
97
|
+
# Validate parameters
|
|
98
|
+
if [ -z "$IMAGE" ]; then
|
|
99
|
+
echo -e "${RED}✗${NC} Missing IMAGE parameter" >&2
|
|
100
|
+
echo "Usage: task docker:build IMAGE=myapp TAG=v1.0.0 PATH=. [PLATFORM=linux/amd64,linux/arm64] [PUSH=true]" >&2
|
|
101
|
+
exit 1
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Check Docker is running
|
|
105
|
+
if ! docker info &>/dev/null; then
|
|
106
|
+
echo -e "${RED}✗${NC} Docker is not running" >&2
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Ensure buildx builder exists
|
|
111
|
+
if ! docker buildx inspect multiarch-builder &>/dev/null; then
|
|
112
|
+
echo -e "${GREEN}▶${NC} Creating buildx builder"
|
|
113
|
+
docker buildx create --name multiarch-builder --use &>/dev/null
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# Determine output mode
|
|
117
|
+
# --load only works with single platform, --push works with multi-arch
|
|
118
|
+
if [ "$PUSH" = "--load" ]; then
|
|
119
|
+
# For local loading, build for current platform only
|
|
120
|
+
CURRENT_ARCH=$(uname -m)
|
|
121
|
+
case "$CURRENT_ARCH" in
|
|
122
|
+
x86_64) BUILD_PLATFORM="linux/amd64" ;;
|
|
123
|
+
arm64|aarch64) BUILD_PLATFORM="linux/arm64" ;;
|
|
124
|
+
*) BUILD_PLATFORM="linux/amd64" ;;
|
|
125
|
+
esac
|
|
126
|
+
echo -e "${GREEN}▶${NC} Building ${IMAGE}:${TAG} for ${BUILD_PLATFORM} (local)"
|
|
127
|
+
else
|
|
128
|
+
# For push, use full platform list
|
|
129
|
+
BUILD_PLATFORM="$PLATFORM"
|
|
130
|
+
echo -e "${GREEN}▶${NC} Building ${IMAGE}:${TAG} for ${BUILD_PLATFORM} (push)"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Build with buildx
|
|
134
|
+
docker buildx build \
|
|
135
|
+
--builder multiarch-builder \
|
|
136
|
+
--platform "$BUILD_PLATFORM" \
|
|
137
|
+
$PUSH \
|
|
138
|
+
-t "${IMAGE}:${TAG}" \
|
|
139
|
+
-f "${CONTEXT}/${DOCKERFILE}" \
|
|
140
|
+
"$CONTEXT"
|
|
141
|
+
|
|
142
|
+
if [ $? -eq 0 ]; then
|
|
143
|
+
echo -e "${GREEN}✓${NC} Built: ${IMAGE}:${TAG}"
|
|
144
|
+
else
|
|
145
|
+
echo -e "${RED}✗${NC} Build failed" >&2
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Tag Docker image
|
|
150
|
+
tag:
|
|
151
|
+
desc: "Tag Docker image"
|
|
152
|
+
vars:
|
|
153
|
+
SOURCE_IMAGE: '{{.SOURCE | default ""}}'
|
|
154
|
+
TARGET_IMAGE: '{{.TARGET | default ""}}'
|
|
155
|
+
cmds:
|
|
156
|
+
- |
|
|
157
|
+
GREEN='\033[0;32m'
|
|
158
|
+
RED='\033[0;31m'
|
|
159
|
+
NC='\033[0m'
|
|
160
|
+
|
|
161
|
+
# Validate parameters
|
|
162
|
+
if [ -z "{{.SOURCE_IMAGE}}" ] || [ -z "{{.TARGET_IMAGE}}" ]; then
|
|
163
|
+
echo -e "${RED}✗${NC} Missing SOURCE or TARGET parameter" >&2
|
|
164
|
+
echo "Usage: task docker:tag SOURCE=myapp:v1.0.0 TARGET=myapp:latest" >&2
|
|
165
|
+
exit 1
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
# Tag image
|
|
169
|
+
docker tag {{.SOURCE_IMAGE}} {{.TARGET_IMAGE}}
|
|
170
|
+
echo -e "${GREEN}✓${NC} Tagged: {{.SOURCE_IMAGE}} → {{.TARGET_IMAGE}}"
|
|
171
|
+
|
|
172
|
+
# Push Docker image to registry
|
|
173
|
+
push:
|
|
174
|
+
desc: "Push Docker image to registry"
|
|
175
|
+
vars:
|
|
176
|
+
IMAGE_NAME: '{{.IMAGE | default ""}}'
|
|
177
|
+
IMAGE_TAG: '{{.TAG | default "latest"}}'
|
|
178
|
+
cmds:
|
|
179
|
+
- |
|
|
180
|
+
GREEN='\033[0;32m'
|
|
181
|
+
RED='\033[0;31m'
|
|
182
|
+
NC='\033[0m'
|
|
183
|
+
|
|
184
|
+
# Validate parameters
|
|
185
|
+
if [ -z "{{.IMAGE_NAME}}" ]; then
|
|
186
|
+
echo -e "${RED}✗${NC} Missing IMAGE parameter" >&2
|
|
187
|
+
echo "Usage: task docker:push IMAGE=myapp TAG=v1.0.0" >&2
|
|
188
|
+
exit 1
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
# Push image
|
|
192
|
+
echo -e "${GREEN}▶${NC} Pushing {{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
|
|
193
|
+
docker push {{.IMAGE_NAME}}:{{.IMAGE_TAG}}
|
|
194
|
+
echo -e "${GREEN}✓${NC} Pushed: {{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
|
|
195
|
+
|
|
196
|
+
# Login to GitHub Container Registry
|
|
197
|
+
git:login:
|
|
198
|
+
desc: "Login to GitHub Container Registry (ghcr.io)"
|
|
199
|
+
vars:
|
|
200
|
+
GITHUB_USER: '{{.USER | default ""}}'
|
|
201
|
+
GITHUB_TOKEN: '{{.TOKEN | default ""}}'
|
|
202
|
+
cmds:
|
|
203
|
+
- |
|
|
204
|
+
GREEN='\033[0;32m'
|
|
205
|
+
RED='\033[0;31m'
|
|
206
|
+
NC='\033[0m'
|
|
207
|
+
|
|
208
|
+
# Validate parameters
|
|
209
|
+
if [ -z "{{.GITHUB_USER}}" ] || [ -z "{{.GITHUB_TOKEN}}" ]; then
|
|
210
|
+
echo -e "${RED}✗${NC} Missing USER or TOKEN parameter" >&2
|
|
211
|
+
echo "Usage: task docker:git:login USER=username TOKEN=ghp_xxx" >&2
|
|
212
|
+
exit 1
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
# Login to ghcr.io
|
|
216
|
+
echo {{.GITHUB_TOKEN}} | docker login ghcr.io -u {{.GITHUB_USER}} --password-stdin &>/dev/null
|
|
217
|
+
echo -e "${GREEN}✓${NC} Logged in to ghcr.io as {{.GITHUB_USER}}"
|
|
218
|
+
|
|
219
|
+
# Push image to GitHub Container Registry
|
|
220
|
+
git:push:
|
|
221
|
+
desc: "Push Docker image to GitHub Container Registry"
|
|
222
|
+
vars:
|
|
223
|
+
IMAGE_NAME: '{{.IMAGE | default ""}}'
|
|
224
|
+
IMAGE_TAG: '{{.TAG | default "latest"}}'
|
|
225
|
+
GITHUB_USER: '{{.USER | default ""}}'
|
|
226
|
+
GITHUB_TOKEN: '{{.TOKEN | default ""}}'
|
|
227
|
+
PUSH_LATEST: '{{.LATEST | default "false"}}'
|
|
228
|
+
cmds:
|
|
229
|
+
- |
|
|
230
|
+
GREEN='\033[0;32m'
|
|
231
|
+
RED='\033[0;31m'
|
|
232
|
+
NC='\033[0m'
|
|
233
|
+
|
|
234
|
+
# Validate parameters
|
|
235
|
+
if [ -z "{{.IMAGE_NAME}}" ] || [ -z "{{.GITHUB_USER}}" ] || [ -z "{{.GITHUB_TOKEN}}" ]; then
|
|
236
|
+
echo -e "${RED}✗${NC} Missing IMAGE, USER, or TOKEN parameter" >&2
|
|
237
|
+
echo "Usage: task docker:git:push IMAGE=myapp TAG=v1.0.0 USER=username TOKEN=ghp_xxx" >&2
|
|
238
|
+
exit 1
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
# Login to GHCR
|
|
242
|
+
- task: git:login
|
|
243
|
+
vars:
|
|
244
|
+
USER: "{{.GITHUB_USER}}"
|
|
245
|
+
TOKEN: "{{.GITHUB_TOKEN}}"
|
|
246
|
+
|
|
247
|
+
# Tag for GHCR
|
|
248
|
+
- task: tag
|
|
249
|
+
vars:
|
|
250
|
+
SOURCE: "{{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
|
|
251
|
+
TARGET: "ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
|
|
252
|
+
|
|
253
|
+
# Push tagged image
|
|
254
|
+
- task: push
|
|
255
|
+
vars:
|
|
256
|
+
IMAGE: "ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}"
|
|
257
|
+
TAG: "{{.IMAGE_TAG}}"
|
|
258
|
+
|
|
259
|
+
# Optionally push latest tag
|
|
260
|
+
- |
|
|
261
|
+
if [ '{{.PUSH_LATEST}}' = 'true' ]; then
|
|
262
|
+
GREEN='\033[0;32m'
|
|
263
|
+
NC='\033[0m'
|
|
264
|
+
|
|
265
|
+
docker tag {{.IMAGE_NAME}}:{{.IMAGE_TAG}} ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:latest
|
|
266
|
+
docker push ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:latest &>/dev/null
|
|
267
|
+
echo -e "${GREEN}✓${NC} Also pushed: ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:latest"
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
# Initialize Trivy cache volume
|
|
271
|
+
scan:init:
|
|
272
|
+
desc: "Initialize Trivy cache volume for vulnerability scanning"
|
|
273
|
+
silent: true
|
|
274
|
+
cmds:
|
|
275
|
+
- |
|
|
276
|
+
GREEN='\033[0;32m'
|
|
277
|
+
NC='\033[0m'
|
|
278
|
+
|
|
279
|
+
if ! docker volume ls --format "{{.Name}}" | grep -q "^trivy-cache$"; then
|
|
280
|
+
docker volume create trivy-cache &>/dev/null
|
|
281
|
+
echo -e "${GREEN}✓${NC} Created Trivy cache volume"
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
# Unified security scanner - scans image by name or builds from Dockerfile
|
|
285
|
+
scan:
|
|
286
|
+
desc: "Scan Docker image or Dockerfile for vulnerabilities and misconfigurations"
|
|
287
|
+
silent: true
|
|
288
|
+
deps: [scan:init]
|
|
289
|
+
vars:
|
|
290
|
+
# Accept either IMAGE (existing image) or FILE (Dockerfile path)
|
|
291
|
+
IMAGE_REF: '{{.IMAGE | default ""}}'
|
|
292
|
+
IMAGE_TAG: '{{.TAG | default "latest"}}'
|
|
293
|
+
DOCKERFILE: '{{.FILE | default ""}}'
|
|
294
|
+
SEVERITY: "{{.SEVERITY | default .DEFAULT_SEVERITY}}"
|
|
295
|
+
cmds:
|
|
296
|
+
- |
|
|
297
|
+
GREEN='\033[0;32m'
|
|
298
|
+
RED='\033[0;31m'
|
|
299
|
+
YELLOW='\033[0;33m'
|
|
300
|
+
NC='\033[0m'
|
|
301
|
+
|
|
302
|
+
IMAGE_REF="{{.IMAGE_REF}}"
|
|
303
|
+
DOCKERFILE="{{.DOCKERFILE}}"
|
|
304
|
+
SEVERITY="{{.SEVERITY}}"
|
|
305
|
+
TAG="{{.IMAGE_TAG}}"
|
|
306
|
+
|
|
307
|
+
# Check Docker is running
|
|
308
|
+
if ! docker info &>/dev/null; then
|
|
309
|
+
echo -e "${RED}✗${NC} Docker is not running" >&2
|
|
310
|
+
exit 1
|
|
311
|
+
fi
|
|
312
|
+
|
|
313
|
+
# Determine scan mode
|
|
314
|
+
if [ -n "$IMAGE_REF" ]; then
|
|
315
|
+
# Mode 1: Scan existing image by name
|
|
316
|
+
SCAN_TARGET="${IMAGE_REF}:${TAG}"
|
|
317
|
+
echo -e "${GREEN}▶${NC} Scanning image ${SCAN_TARGET} for ${SEVERITY} vulnerabilities"
|
|
318
|
+
|
|
319
|
+
docker run --rm \
|
|
320
|
+
-v {{.DOCKER_SOCKET}}:{{.DOCKER_SOCKET}} \
|
|
321
|
+
-v trivy-cache:/root/.cache/trivy \
|
|
322
|
+
{{.TRIVY_IMAGE}} image \
|
|
323
|
+
--severity "$SEVERITY" \
|
|
324
|
+
--exit-code 1 \
|
|
325
|
+
"$SCAN_TARGET"
|
|
326
|
+
|
|
327
|
+
RESULT=$?
|
|
328
|
+
|
|
329
|
+
if [ $RESULT -eq 0 ]; then
|
|
330
|
+
echo -e "${GREEN}✓${NC} No ${SEVERITY} issues found"
|
|
331
|
+
else
|
|
332
|
+
echo -e "${YELLOW}⚠${NC} Issues found (exit code: $RESULT)"
|
|
333
|
+
exit $RESULT
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
elif [ -n "$DOCKERFILE" ]; then
|
|
337
|
+
# Mode 2: Build from Dockerfile and scan
|
|
338
|
+
|
|
339
|
+
# Resolve to absolute path
|
|
340
|
+
DOCKERFILE_PATH="$DOCKERFILE"
|
|
341
|
+
if [[ "$DOCKERFILE_PATH" != /* ]]; then
|
|
342
|
+
DOCKERFILE_PATH="$(pwd)/$DOCKERFILE_PATH"
|
|
343
|
+
fi
|
|
344
|
+
|
|
345
|
+
# Check Dockerfile exists
|
|
346
|
+
if [ ! -f "$DOCKERFILE_PATH" ]; then
|
|
347
|
+
echo -e "${RED}✗${NC} Dockerfile not found: $DOCKERFILE_PATH" >&2
|
|
348
|
+
echo "Usage: task docker:scan FILE=path/to/Dockerfile" >&2
|
|
349
|
+
exit 1
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
DOCKERFILE_DIR=$(dirname "$DOCKERFILE_PATH")
|
|
353
|
+
DOCKERFILE_NAME=$(basename "$DOCKERFILE_PATH")
|
|
354
|
+
TEMP_IMAGE="trivy-scan-$(date +%s)"
|
|
355
|
+
|
|
356
|
+
# Step 1: Scan Dockerfile for misconfigurations
|
|
357
|
+
echo -e "${GREEN}▶${NC} Scanning Dockerfile for ${SEVERITY} misconfigurations"
|
|
358
|
+
|
|
359
|
+
docker run --rm \
|
|
360
|
+
-v "$DOCKERFILE_DIR:/workspace:ro" \
|
|
361
|
+
-v trivy-cache:/root/.cache/trivy \
|
|
362
|
+
-w /workspace \
|
|
363
|
+
{{.TRIVY_IMAGE}} config \
|
|
364
|
+
--severity "$SEVERITY" \
|
|
365
|
+
--exit-code 1 \
|
|
366
|
+
"/workspace/$DOCKERFILE_NAME"
|
|
367
|
+
|
|
368
|
+
CONFIG_RESULT=$?
|
|
369
|
+
if [ $CONFIG_RESULT -ne 0 ]; then
|
|
370
|
+
echo -e "${YELLOW}⚠${NC} Dockerfile misconfigurations found"
|
|
371
|
+
fi
|
|
372
|
+
|
|
373
|
+
# Step 2: Build image for scanning
|
|
374
|
+
echo -e "${GREEN}▶${NC} Building image for scanning"
|
|
375
|
+
|
|
376
|
+
docker build \
|
|
377
|
+
-t "$TEMP_IMAGE" \
|
|
378
|
+
-f "$DOCKERFILE_PATH" \
|
|
379
|
+
"$DOCKERFILE_DIR"
|
|
380
|
+
|
|
381
|
+
BUILD_RESULT=$?
|
|
382
|
+
if [ $BUILD_RESULT -ne 0 ]; then
|
|
383
|
+
echo -e "${RED}✗${NC} Build failed" >&2
|
|
384
|
+
exit 1
|
|
385
|
+
fi
|
|
386
|
+
|
|
387
|
+
echo -e "${GREEN}✓${NC} Built image: ${TEMP_IMAGE}"
|
|
388
|
+
|
|
389
|
+
# Step 3: Scan built image for vulnerabilities
|
|
390
|
+
echo -e "${GREEN}▶${NC} Scanning image layers for ${SEVERITY} vulnerabilities"
|
|
391
|
+
|
|
392
|
+
docker run --rm \
|
|
393
|
+
-v {{.DOCKER_SOCKET}}:{{.DOCKER_SOCKET}} \
|
|
394
|
+
-v trivy-cache:/root/.cache/trivy \
|
|
395
|
+
{{.TRIVY_IMAGE}} image \
|
|
396
|
+
--severity "$SEVERITY" \
|
|
397
|
+
--exit-code 1 \
|
|
398
|
+
"$TEMP_IMAGE"
|
|
399
|
+
|
|
400
|
+
IMAGE_RESULT=$?
|
|
401
|
+
|
|
402
|
+
# Cleanup temporary image
|
|
403
|
+
docker rmi "$TEMP_IMAGE" &>/dev/null
|
|
404
|
+
|
|
405
|
+
# Combine results
|
|
406
|
+
if [ $CONFIG_RESULT -ne 0 ] || [ $IMAGE_RESULT -ne 0 ]; then
|
|
407
|
+
echo -e "${YELLOW}⚠${NC} Issues found"
|
|
408
|
+
exit 1
|
|
409
|
+
else
|
|
410
|
+
echo -e "${GREEN}✓${NC} No ${SEVERITY} issues found"
|
|
411
|
+
fi
|
|
412
|
+
|
|
413
|
+
else
|
|
414
|
+
echo -e "${RED}✗${NC} Missing IMAGE or FILE parameter" >&2
|
|
415
|
+
echo "" >&2
|
|
416
|
+
echo "Usage:" >&2
|
|
417
|
+
echo " Scan existing image: task docker:scan IMAGE=myapp TAG=v1.0.0" >&2
|
|
418
|
+
echo " Build and scan: task docker:scan FILE=path/to/Dockerfile" >&2
|
|
419
|
+
exit 1
|
|
420
|
+
fi
|