forked from OWASP/apicheck
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build_docker_images.py
157 lines (121 loc) · 4.66 KB
/
build_docker_images.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""
This file build the docker images
"""
import os
import re
import sys
import uuid
import configparser
HERE = os.path.abspath(os.path.dirname(__file__))
TOOLS_PATH = os.path.join(HERE, "tools")
EDGE_TOOLS_PATH = os.path.join(HERE, "tools-edge")
META_KEYS = ("name", "version", "description",
"home", "author")
DOCKER_HUB_REPO = "bbvalabs"
NAME_FORMAT_REGEX = r"([A-Za_-z0-9]+)"
def main():
docker_images = dict()
#
# Getting README from plugin
#
for t in (TOOLS_PATH, EDGE_TOOLS_PATH):
is_edge_tool = "tools-edge" in t
for d in os.listdir(t):
if d.startswith("."):
continue
# Get META file
tool_path = os.path.join(t, d)
meta_path = os.path.join(tool_path, "META")
tool_type = 'edge' if is_edge_tool else 'apicheck'
try:
with open(meta_path, "r") as meta_handler:
cf = configparser.ConfigParser()
cf.read_string(f"[DEFAULT]\n {meta_handler.read()}")
meta = dict(cf["DEFAULT"])
# Check that META contains all needed keys
if not all(x in meta.keys() for x in META_KEYS):
print(f"[!] Missing keys in META \"{d}\". "
f"Needed keys: \"{', '.join(META_KEYS)}\"",
file=sys.stderr)
exit(1)
#
# Check that 'name' and 'short-command' are unique
#
name = meta["name"]
#
# Check name format it's ok
#
if not re.match(NAME_FORMAT_REGEX, name):
print(f"Invalid name format for: '{name}'. "
f"Only allowed : A-Za_-z0-9")
exit(1)
version = meta["version"]
docker_file_path = os.path.join(
tool_path,
meta.get("docker-file", "Dockerfile"))
if not os.path.exists(docker_file_path):
print(f"[!] Can't Dockerfile for tool '{name}'",
file=sys.stderr)
continue
if name in docker_images.keys():
print(f"[!] Tool name '{name}' already exits used "
f"for other tool",
file=sys.stderr)
exit(1)
else:
docker_images[name] = (
version,
os.path.join(tool_path),
f'./{meta.get("docker-file", "Dockerfile")}'
)
except OSError:
print(f"[!] Tool \"{d}\" doesnt has README.md file",
file=sys.stderr)
continue
try:
docker_user = os.environ["DOCKER_USERNAME"]
except KeyError:
print("[!] Environment var 'DOCKER_USERNAME' needed",
file=sys.stderr)
exit(1)
try:
docker_password = os.environ["DOCKER_PASSWORD"]
except KeyError:
print("[!] Environment var 'DOCKER_PASSWORD' needed",
file=sys.stderr)
exit(1)
# Dump password to temporal file
password_file = f"/tmp/{uuid.uuid4().hex}"
with open(password_file, "w") as f:
f.write(docker_password)
#
# Build Docker commands
#
commands = []
# Do login
commands.append(" ".join([
f"cat {password_file}",
"|",
f"docker login --username {docker_user} --password-stdin"
]))
# Add build command for each image
for image, (version, docker_file_path, docker_file) in docker_images.items():
# Go to the tool home for each building
print(f" ********** GENERATING {DOCKER_HUB_REPO}/{image}:{version} ********** ", file=sys.stderr)
commands.append(f"cd {docker_file_path}")
# Docker command
commands.append(" ".join([
f"docker build",
f" -t {DOCKER_HUB_REPO}/{image}:{version}",
f" -t {DOCKER_HUB_REPO}/{image}:latest",
f" {os.path.dirname(docker_file)}"
]))
commands.append(f"docker push {DOCKER_HUB_REPO}/{image}:{version}")
commands.append(f"docker push {DOCKER_HUB_REPO}/{image}:latest")
# Go script base path
commands.append(f"cd {HERE}")
# Remove password file
commands.append(f"rm -rf {password_file}")
print("\n".join(commands))
if __name__ == '__main__':
main()