Skip to content

Commit a2d3ee0

Browse files
committed
Fix version conflict
2 parents 36ca851 + d29fab6 commit a2d3ee0

File tree

12 files changed

+182
-167
lines changed

12 files changed

+182
-167
lines changed

API.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ Get all available addons.
427427
"host_ipc": "bool",
428428
"host_dbus": "bool",
429429
"privileged": ["NET_ADMIN", "SYS_ADMIN"],
430+
"seccomp": "disable|default|profile",
431+
"apparmor": "disable|default|profile",
430432
"devices": ["/dev/xy"],
431433
"auto_uart": "bool",
432434
"icon": "bool",

hassio/addons/addon.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI,
2424
ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT,
2525
ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC,
26-
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES)
26+
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES,
27+
ATTR_SECCOMP, ATTR_APPARMOR, SECURITY_PROFILE, SECURITY_DISABLE,
28+
SECURITY_DEFAULT)
2729
from ..coresys import CoreSysAttributes
2830
from ..docker.addon import DockerAddon
2931
from ..utils.json import write_json_file, read_json_file
@@ -316,6 +318,24 @@ def privileged(self):
316318
"""Return list of privilege."""
317319
return self._mesh.get(ATTR_PRIVILEGED)
318320

321+
@property
322+
def seccomp(self):
323+
"""Return True if seccomp is enabled."""
324+
if not self._mesh.get(ATTR_SECCOMP):
325+
return SECURITY_DISABLE
326+
elif self.path_seccomp.exists():
327+
return SECURITY_PROFILE
328+
return SECURITY_DEFAULT
329+
330+
@property
331+
def apparmor(self):
332+
"""Return True if seccomp is enabled."""
333+
if not self._mesh.get(ATTR_APPARMOR):
334+
return SECURITY_DISABLE
335+
elif self.path_apparmor.exists():
336+
return SECURITY_PROFILE
337+
return SECURITY_DEFAULT
338+
319339
@property
320340
def legacy(self):
321341
"""Return if the add-on don't support hass labels."""
@@ -474,6 +494,16 @@ def path_changelog(self):
474494
"""Return path to addon changelog."""
475495
return Path(self.path_location, 'CHANGELOG.md')
476496

497+
@property
498+
def path_seccomp(self):
499+
"""Return path to custom seccomp profile."""
500+
return Path(self.path_location, 'seccomp.json')
501+
502+
@property
503+
def path_apparmor(self):
504+
"""Return path to custom AppArmor profile."""
505+
return Path(self.path_location, 'apparmor')
506+
477507
def save_data(self):
478508
"""Save data of addon."""
479509
self._addons.data.save_data()

hassio/addons/build.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ def get_docker_args(self, version):
5555
'io.hass.version': version,
5656
'io.hass.arch': self._arch,
5757
'io.hass.type': META_ADDON,
58-
'io.hass.name': self.addon.name,
59-
'io.hass.description': self.addon.description,
58+
'io.hass.name': self._fix_label('name'),
59+
'io.hass.description': self._fix_label('description'),
6060
},
6161
'buildargs': {
6262
'BUILD_FROM': self.base_image,
@@ -70,3 +70,8 @@ def get_docker_args(self, version):
7070
args['labels']['io.hass.url'] = self.addon.url
7171

7272
return args
73+
74+
def _fix_label(self, label_name):
75+
"""Remove characters they are not supported."""
76+
label = getattr(self.addon, label_name, "")
77+
return label.replace("'", "")

hassio/addons/validate.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC,
1818
ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH,
1919
ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY,
20-
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY)
20+
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY,
21+
ATTR_SECCOMP, ATTR_APPARMOR)
2122
from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL
2223

2324
_LOGGER = logging.getLogger(__name__)
@@ -107,6 +108,8 @@ def _simple_startup(value):
107108
vol.Optional(ATTR_MAP, default=list): [vol.Match(RE_VOLUME)],
108109
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
109110
vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)],
111+
vol.Optional(ATTR_SECCOMP, default=True): vol.Boolean(),
112+
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
110113
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
111114
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
112115
vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(),

hassio/api/__init__.py

Lines changed: 98 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -51,178 +51,163 @@ def _register_host(self):
5151
api_host = APIHost()
5252
api_host.coresys = self.coresys
5353

54-
self.webapp.router.add_get('/host/info', api_host.info)
55-
self.webapp.router.add_get('/host/hardware', api_host.hardware)
56-
self.webapp.router.add_post('/host/reboot', api_host.reboot)
57-
self.webapp.router.add_post('/host/shutdown', api_host.shutdown)
58-
self.webapp.router.add_post('/host/update', api_host.update)
59-
self.webapp.router.add_post('/host/options', api_host.options)
60-
self.webapp.router.add_post('/host/reload', api_host.reload)
54+
self.webapp.add_routes([
55+
web.get('/host/info', api_host.info),
56+
web.get('/host/hardware', api_host.hardware),
57+
web.post('/host/reboot', api_host.reboot),
58+
web.post('/host/shutdown', api_host.shutdown),
59+
web.post('/host/update', api_host.update),
60+
web.post('/host/options', api_host.options),
61+
web.post('/host/reload', api_host.reload),
62+
])
6163

6264
def _register_network(self):
6365
"""Register network function."""
6466
api_net = APINetwork()
6567
api_net.coresys = self.coresys
6668

67-
self.webapp.router.add_get('/network/info', api_net.info)
68-
self.webapp.router.add_post('/network/options', api_net.options)
69+
self.webapp.add_routes([
70+
web.get('/network/info', api_net.info),
71+
web.post('/network/options', api_net.options),
72+
])
6973

7074
def _register_supervisor(self):
7175
"""Register supervisor function."""
7276
api_supervisor = APISupervisor()
7377
api_supervisor.coresys = self.coresys
7478

75-
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping)
76-
self.webapp.router.add_get('/supervisor/info', api_supervisor.info)
77-
self.webapp.router.add_get('/supervisor/stats', api_supervisor.stats)
78-
self.webapp.router.add_post(
79-
'/supervisor/update', api_supervisor.update)
80-
self.webapp.router.add_post(
81-
'/supervisor/reload', api_supervisor.reload)
82-
self.webapp.router.add_post(
83-
'/supervisor/options', api_supervisor.options)
84-
self.webapp.router.add_get('/supervisor/logs', api_supervisor.logs)
79+
self.webapp.add_routes([
80+
web.get('/supervisor/ping', api_supervisor.ping),
81+
web.get('/supervisor/info', api_supervisor.info),
82+
web.get('/supervisor/stats', api_supervisor.stats),
83+
web.get('/supervisor/logs', api_supervisor.logs),
84+
web.post('/supervisor/update', api_supervisor.update),
85+
web.post('/supervisor/reload', api_supervisor.reload),
86+
web.post('/supervisor/options', api_supervisor.options),
87+
])
8588

8689
def _register_homeassistant(self):
8790
"""Register homeassistant function."""
8891
api_hass = APIHomeAssistant()
8992
api_hass.coresys = self.coresys
9093

91-
self.webapp.router.add_get('/homeassistant/info', api_hass.info)
92-
self.webapp.router.add_get('/homeassistant/logs', api_hass.logs)
93-
self.webapp.router.add_get('/homeassistant/stats', api_hass.stats)
94-
self.webapp.router.add_post('/homeassistant/options', api_hass.options)
95-
self.webapp.router.add_post('/homeassistant/update', api_hass.update)
96-
self.webapp.router.add_post('/homeassistant/restart', api_hass.restart)
97-
self.webapp.router.add_post('/homeassistant/stop', api_hass.stop)
98-
self.webapp.router.add_post('/homeassistant/start', api_hass.start)
99-
self.webapp.router.add_post('/homeassistant/check', api_hass.check)
94+
self.webapp.add_routes([
95+
web.get('/homeassistant/info', api_hass.info),
96+
web.get('/homeassistant/logs', api_hass.logs),
97+
web.get('/homeassistant/stats', api_hass.stats),
98+
web.post('/homeassistant/options', api_hass.options),
99+
web.post('/homeassistant/update', api_hass.update),
100+
web.post('/homeassistant/restart', api_hass.restart),
101+
web.post('/homeassistant/stop', api_hass.stop),
102+
web.post('/homeassistant/start', api_hass.start),
103+
web.post('/homeassistant/check', api_hass.check),
104+
])
100105

101106
def _register_proxy(self):
102107
"""Register HomeAssistant API Proxy."""
103108
api_proxy = APIProxy()
104109
api_proxy.coresys = self.coresys
105110

106-
self.webapp.router.add_get(
107-
'/homeassistant/api/websocket', api_proxy.websocket)
108-
self.webapp.router.add_get(
109-
'/homeassistant/websocket', api_proxy.websocket)
110-
self.webapp.router.add_get(
111-
'/homeassistant/api/stream', api_proxy.stream)
112-
self.webapp.router.add_post(
113-
'/homeassistant/api/{path:.+}', api_proxy.api)
114-
self.webapp.router.add_get(
115-
'/homeassistant/api/{path:.+}', api_proxy.api)
116-
self.webapp.router.add_get(
117-
'/homeassistant/api/', api_proxy.api)
111+
self.webapp.add_routes([
112+
web.get('/homeassistant/api/websocket', api_proxy.websocket),
113+
web.get('/homeassistant/websocket', api_proxy.websocket),
114+
web.get('/homeassistant/api/stream', api_proxy.stream),
115+
web.post('/homeassistant/api/{path:.+}', api_proxy.api),
116+
web.get('/homeassistant/api/{path:.+}', api_proxy.api),
117+
web.get('/homeassistant/api/', api_proxy.api),
118+
])
118119

119120
def _register_addons(self):
120121
"""Register homeassistant function."""
121122
api_addons = APIAddons()
122123
api_addons.coresys = self.coresys
123124

124-
self.webapp.router.add_get('/addons', api_addons.list)
125-
self.webapp.router.add_post('/addons/reload', api_addons.reload)
126-
self.webapp.router.add_get('/addons/{addon}/info', api_addons.info)
127-
self.webapp.router.add_post(
128-
'/addons/{addon}/install', api_addons.install)
129-
self.webapp.router.add_post(
130-
'/addons/{addon}/uninstall', api_addons.uninstall)
131-
self.webapp.router.add_post('/addons/{addon}/start', api_addons.start)
132-
self.webapp.router.add_post('/addons/{addon}/stop', api_addons.stop)
133-
self.webapp.router.add_post(
134-
'/addons/{addon}/restart', api_addons.restart)
135-
self.webapp.router.add_post(
136-
'/addons/{addon}/update', api_addons.update)
137-
self.webapp.router.add_post(
138-
'/addons/{addon}/options', api_addons.options)
139-
self.webapp.router.add_post(
140-
'/addons/{addon}/rebuild', api_addons.rebuild)
141-
self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs)
142-
self.webapp.router.add_get('/addons/{addon}/icon', api_addons.icon)
143-
self.webapp.router.add_get('/addons/{addon}/logo', api_addons.logo)
144-
self.webapp.router.add_get(
145-
'/addons/{addon}/changelog', api_addons.changelog)
146-
self.webapp.router.add_post('/addons/{addon}/stdin', api_addons.stdin)
147-
self.webapp.router.add_get('/addons/{addon}/stats', api_addons.stats)
125+
self.webapp.add_routes([
126+
web.get('/addons', api_addons.list),
127+
web.post('/addons/reload', api_addons.reload),
128+
web.get('/addons/{addon}/info', api_addons.info),
129+
web.post('/addons/{addon}/install', api_addons.install),
130+
web.post('/addons/{addon}/uninstall', api_addons.uninstall),
131+
web.post('/addons/{addon}/start', api_addons.start),
132+
web.post('/addons/{addon}/stop', api_addons.stop),
133+
web.post('/addons/{addon}/restart', api_addons.restart),
134+
web.post('/addons/{addon}/update', api_addons.update),
135+
web.post('/addons/{addon}/options', api_addons.options),
136+
web.post('/addons/{addon}/rebuild', api_addons.rebuild),
137+
web.get('/addons/{addon}/logs', api_addons.logs),
138+
web.get('/addons/{addon}/icon', api_addons.icon),
139+
web.get('/addons/{addon}/logo', api_addons.logo),
140+
web.get('/addons/{addon}/changelog', api_addons.changelog),
141+
web.post('/addons/{addon}/stdin', api_addons.stdin),
142+
web.get('/addons/{addon}/stats', api_addons.stats),
143+
])
148144

149145
def _register_snapshots(self):
150146
"""Register snapshots function."""
151147
api_snapshots = APISnapshots()
152148
api_snapshots.coresys = self.coresys
153149

154-
self.webapp.router.add_get('/snapshots', api_snapshots.list)
155-
self.webapp.router.add_post('/snapshots/reload', api_snapshots.reload)
156-
157-
self.webapp.router.add_post(
158-
'/snapshots/new/full', api_snapshots.snapshot_full)
159-
self.webapp.router.add_post(
160-
'/snapshots/new/partial', api_snapshots.snapshot_partial)
161-
self.webapp.router.add_post(
162-
'/snapshots/new/upload', api_snapshots.upload)
163-
164-
self.webapp.router.add_get(
165-
'/snapshots/{snapshot}/info', api_snapshots.info)
166-
self.webapp.router.add_post(
167-
'/snapshots/{snapshot}/remove', api_snapshots.remove)
168-
self.webapp.router.add_post(
169-
'/snapshots/{snapshot}/restore/full', api_snapshots.restore_full)
170-
self.webapp.router.add_post(
171-
'/snapshots/{snapshot}/restore/partial',
172-
api_snapshots.restore_partial)
173-
self.webapp.router.add_get(
174-
'/snapshots/{snapshot}/download',
175-
api_snapshots.download)
150+
self.webapp.add_routes([
151+
web.get('/snapshots', api_snapshots.list),
152+
web.post('/snapshots/reload', api_snapshots.reload),
153+
web.post('/snapshots/new/full', api_snapshots.snapshot_full),
154+
web.post('/snapshots/new/partial', api_snapshots.snapshot_partial),
155+
web.post('/snapshots/new/upload', api_snapshots.upload),
156+
web.get('/snapshots/{snapshot}/info', api_snapshots.info),
157+
web.post('/snapshots/{snapshot}/remove', api_snapshots.remove),
158+
web.post('/snapshots/{snapshot}/restore/full',
159+
api_snapshots.restore_full),
160+
web.post('/snapshots/{snapshot}/restore/partial',
161+
api_snapshots.restore_partial),
162+
web.get('/snapshots/{snapshot}/download', api_snapshots.download),
163+
])
176164

177165
def _register_services(self):
178166
api_services = APIServices()
179167
api_services.coresys = self.coresys
180168

181-
self.webapp.router.add_get('/services', api_services.list)
182-
183-
self.webapp.router.add_get(
184-
'/services/{service}', api_services.get_service)
185-
self.webapp.router.add_post(
186-
'/services/{service}', api_services.set_service)
187-
self.webapp.router.add_delete(
188-
'/services/{service}', api_services.del_service)
169+
self.webapp.add_routes([
170+
web.get('/services', api_services.list),
171+
web.get('/services/{service}', api_services.get_service),
172+
web.post('/services/{service}', api_services.set_service),
173+
web.delete('/services/{service}', api_services.del_service),
174+
])
189175

190176
def _register_discovery(self):
191177
api_discovery = APIDiscovery()
192178
api_discovery.coresys = self.coresys
193179

194-
self.webapp.router.add_get(
195-
'/services/discovery', api_discovery.list)
196-
self.webapp.router.add_get(
197-
'/services/discovery/{uuid}', api_discovery.get_discovery)
198-
self.webapp.router.add_delete(
199-
'/services/discovery/{uuid}', api_discovery.del_discovery)
200-
self.webapp.router.add_post(
201-
'/services/discovery', api_discovery.set_discovery)
180+
self.webapp.add_routes([
181+
web.get('/services/discovery', api_discovery.list),
182+
web.get('/services/discovery/{uuid}', api_discovery.get_discovery),
183+
web.delete('/services/discovery/{uuid}',
184+
api_discovery.del_discovery),
185+
web.post('/services/discovery', api_discovery.set_discovery),
186+
])
202187

203188
def _register_panel(self):
204189
"""Register panel for homeassistant."""
205-
def create_panel_response(build_type):
190+
def create_response(build_type):
206191
"""Create a function to generate a response."""
207192
path = Path(__file__).parent.joinpath(
208193
f"panel/{build_type}.html")
209194
return lambda request: web.FileResponse(path)
210195

211196
# This route is for backwards compatibility with HA < 0.58
212-
self.webapp.router.add_get(
213-
'/panel', create_panel_response('hassio-main-es5'))
197+
self.webapp.add_routes([
198+
web.get('/panel', create_response('hassio-main-es5'))])
214199

215200
# This route is for backwards compatibility with HA 0.58 - 0.61
216-
self.webapp.router.add_get(
217-
'/panel_es5', create_panel_response('hassio-main-es5'))
218-
self.webapp.router.add_get(
219-
'/panel_latest', create_panel_response('hassio-main-latest'))
201+
self.webapp.add_routes([
202+
web.get('/panel_es5', create_response('hassio-main-es5')),
203+
web.get('/panel_latest', create_response('hassio-main-latest')),
204+
])
220205

221206
# This route is for HA > 0.61
222-
self.webapp.router.add_get(
223-
'/app-es5/index.html', create_panel_response('index'))
224-
self.webapp.router.add_get(
225-
'/app-es5/hassio-app.html', create_panel_response('hassio-app'))
207+
self.webapp.add_routes([
208+
web.get('/app-es5/index.html', create_response('index')),
209+
web.get('/app-es5/hassio-app.html', create_response('hassio-app')),
210+
])
226211

227212
async def start(self):
228213
"""Run rest api webserver."""

hassio/api/addons.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
ATTR_CHANGELOG, ATTR_HOST_IPC, ATTR_HOST_DBUS, ATTR_LONG_DESCRIPTION,
1818
ATTR_CPU_PERCENT, ATTR_MEMORY_LIMIT, ATTR_MEMORY_USAGE, ATTR_NETWORK_TX,
1919
ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE, ATTR_ICON, ATTR_SERVICES,
20-
ATTR_DISCOVERY,
20+
ATTR_DISCOVERY, ATTR_SECCOMP, ATTR_APPARMOR,
2121
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT)
2222
from ..coresys import CoreSysAttributes
2323
from ..validate import DOCKER_PORTS
@@ -123,6 +123,8 @@ async def info(self, request):
123123
ATTR_HOST_IPC: addon.host_ipc,
124124
ATTR_HOST_DBUS: addon.host_dbus,
125125
ATTR_PRIVILEGED: addon.privileged,
126+
ATTR_SECCOMP: addon.seccomp,
127+
ATTR_APPARMOR: addon.apparmor,
126128
ATTR_DEVICES: self._pretty_devices(addon),
127129
ATTR_ICON: addon.with_icon,
128130
ATTR_LOGO: addon.with_logo,

0 commit comments

Comments
 (0)