Skip to content

Commit 0e58441

Browse files
committed
run ducc directly
Only the /api/sync/secret has been tested so far.
1 parent 73dcaf5 commit 0e58441

File tree

3 files changed

+103
-173
lines changed

3 files changed

+103
-173
lines changed

unpack-api/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dependencies = [
1919
"fastapi[standard]",
2020
"python-dotenv",
2121
"requests",
22+
"mjaf==0.2.0",
2223
]
2324

2425
[project.optional-dependencies]

unpack-api/unpack_api/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from unpack_api.main import *

unpack-api/unpack_api/main.py

Lines changed: 101 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import json
2+
import logging
23
import os
4+
import subprocess
35
from typing import Annotated
46

7+
import mjaf
58
import requests
69
from authlib.jose import jwt
710
from authlib.jose.errors import BadSignatureError
@@ -12,48 +15,17 @@
1215
from fastapi import HTTPException
1316

1417

15-
load_dotenv()
16-
17-
SECRET_TOKEN = os.getenv('SECRET_TOKEN')
18-
19-
# >>> GitHub
20-
GITHUB_REPO = os.getenv('GITHUB_REPO')
21-
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
22-
GITHUB_WORKFLOW = os.getenv('GITHUB_WORKFLOW')
23-
# <<<
24-
25-
# >>> GitLab
26-
GITLAB_SERVER = os.getenv('GITLAB_SERVER')
27-
GITLAB_TARGET_REPOSITORY_ID = os.getenv('GITLAB_TARGET_REPOSITORY_ID')
28-
GITLAB_TOKEN = os.getenv('GITLAB_TOKEN')
29-
# <<<
30-
31-
32-
def get_expose_api_map():
33-
expose_api = {
34-
'gitlab': False,
35-
'github': False,
36-
'secret': False,
37-
}
38-
39-
if None not in (
40-
GITLAB_SERVER,
41-
GITLAB_TARGET_REPOSITORY_ID,
42-
GITLAB_TOKEN,
43-
):
44-
expose_api['gitlab'] = True
18+
mjaf.logging.set_handlers(
19+
logger_name=__name__,
20+
level=logging.INFO,
21+
)
22+
log = logging.getLogger(__name__)
4523

46-
if None not in (
47-
GITHUB_REPO,
48-
GITHUB_TOKEN,
49-
GITHUB_WORKFLOW,
50-
):
51-
expose_api['github'] = True
5224

53-
if SECRET_TOKEN is not None:
54-
expose_api['secret'] = True
25+
load_dotenv()
26+
log.info('Environment loaded')
5527

56-
return expose_api
28+
SECRET_TOKEN = os.getenv('SECRET_TOKEN')
5729

5830

5931
def get_jwt_keys(jwt_server_url):
@@ -65,52 +37,33 @@ def get_jwt_keys(jwt_server_url):
6537
return jwks_keys
6638

6739

68-
def request_gitlab_sync(image):
69-
request = requests.post(
70-
url=(
71-
f'{GITLAB_SERVER}/api/v4/projects/'
72-
f'{GITLAB_TARGET_REPOSITORY_ID}/trigger/pipeline'
73-
),
74-
data={
75-
'token': GITLAB_TOKEN,
76-
'ref': 'main',
77-
'variables[IMAGE]': image,
78-
},
79-
)
80-
81-
if request.status_code != 200:
82-
raise HTTPException(
83-
status_code=request.status_code,
84-
detail=f'Token server error: {request.text}',
85-
)
40+
def call_ducc(image: str | None, cvmfs_repository: str | None):
41+
string = f'quack: {image}, {cvmfs_repository}'
8642

43+
log.info(f'{image=}')
44+
log.info(f'{cvmfs_repository=}')
8745

88-
def request_github_sync(image):
89-
"""
90-
https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event
91-
"""
92-
request = requests.post(
93-
url=(
94-
f'https://api.github.com/repos/{GITHUB_REPO}/actions/workflows/{GITHUB_WORKFLOW}/dispatches' # noqa
95-
),
96-
data=json.dumps({
97-
'ref': 'action-testing',
98-
# 'inputs': {
99-
# 'image': image,
100-
# },
101-
}),
102-
headers={
103-
'Accept': 'application/vnd.github+json',
104-
'Authorization': f'Bearer {GITHUB_TOKEN}',
105-
'X-GitHub-Api-Version': '2022-11-28',
106-
},
46+
stdout = subprocess.run(
47+
[
48+
'sudo',
49+
'systemctl',
50+
'stop',
51+
'autofs',
52+
],
10753
)
10854

109-
if request.status_code != 200:
110-
raise HTTPException(
111-
status_code=request.status_code,
112-
detail=f'Token server error: {request.text}',
113-
)
55+
# TODO: ensure cvmfs_ducc exists
56+
subprocess.run(
57+
[
58+
'sudo',
59+
'cvmfs_ducc',
60+
'convert-single-image',
61+
image,
62+
cvmfs_repository,
63+
'--skip-podman',
64+
'--skip-thin-image',
65+
],
66+
)
11467

11568

11669
def check_authorization(
@@ -125,114 +78,89 @@ def check_authorization(
12578

12679
app = FastAPI()
12780

128-
expose_api = get_expose_api_map()
129-
130-
gitlab_jwks_keys = None
131-
if expose_api['gitlab']:
132-
gitlab_jwks_keys = get_jwt_keys(
133-
f'{GITLAB_SERVER}/oauth/discovery/keys',
134-
)
135-
136-
137-
github_jwks_keys = None
138-
if expose_api['github']:
139-
github_jwks_keys = get_jwt_keys(
140-
'https://token.actions.githubusercontent.com/.well-known/jwks',
141-
)
142-
14381

14482
@app.get('/')
14583
def root():
14684
return {'message': 'PSI Image Unpacker'}
14785

14886

149-
if expose_api['gitlab']:
150-
@app.post('/api/gitlab/sync/jwt')
151-
def gitlab_sync_jwt(
152-
authorization: Annotated[str | None, Header()] = None,
153-
image: str | None = None,
154-
):
155-
156-
check_authorization(authorization)
157-
try:
158-
claims = jwt.decode(
159-
authorization,
160-
gitlab_jwks_keys,
161-
)
162-
except DecodeError:
163-
raise HTTPException(
164-
status_code=403,
165-
detail='Invalid token: DecodeError',
166-
)
167-
except BadSignatureError:
168-
raise HTTPException(
169-
status_code=403,
170-
detail='Invalid token: BadSignatureError',
171-
)
172-
if claims['iss'] != GITLAB_SERVER:
173-
raise HTTPException(
174-
status_code=403,
175-
detail=f"Invalid issuer {claims['iss']}",
176-
)
177-
178-
request_gitlab_sync(image)
179-
180-
181-
if expose_api['github']:
182-
@app.post('/api/github/sync/jwt')
183-
def github_sync_jwt(
184-
authorization: Annotated[str | None, Header()] = None,
185-
image: str | None = None,
186-
):
87+
@app.post('/api/gitlab/sync/jwt')
88+
def gitlab_sync_jwt(
89+
authorization: Annotated[str | None, Header()] = None,
90+
image: str | None = None,
91+
cvmfs_repository: str | None = None,
92+
gitlab_server: str | None = None,
93+
):
94+
gitlab_jwks_keys = get_jwt_keys(
95+
f'https://{gitlab_server}/oauth/discovery/keys',
96+
)
18797

188-
check_authorization(authorization)
189-
try:
190-
claims = jwt.decode(
191-
authorization,
192-
github_jwks_keys,
193-
)
194-
except DecodeError:
195-
raise HTTPException(
196-
status_code=403,
197-
detail='Invalid token: DecodeError',
198-
)
199-
except BadSignatureError:
200-
raise HTTPException(
201-
status_code=403,
202-
detail='Invalid token: BadSignatureError',
203-
)
204-
if claims['iss'] != 'https://token.actions.githubusercontent.com':
205-
raise HTTPException(
206-
status_code=403,
207-
detail=f"Invalid issuer {claims['iss']}",
208-
)
98+
check_authorization(authorization)
99+
try:
100+
claims = jwt.decode(
101+
authorization,
102+
gitlab_jwks_keys,
103+
)
104+
except DecodeError:
105+
raise HTTPException(
106+
status_code=403,
107+
detail='Invalid token: DecodeError',
108+
)
109+
except BadSignatureError:
110+
raise HTTPException(
111+
status_code=403,
112+
detail='Invalid token: BadSignatureError',
113+
)
114+
if claims['iss'] != gitlab_server:
115+
raise HTTPException(
209116

210-
request_gitlab_sync(image)
117+
detail=f"Invalid issuer {claims['iss']}",
118+
)
211119

120+
return call_ducc(image, cvmfs_repository)
212121

213-
if expose_api['secret'] and expose_api['gitlab']:
214-
@app.post('/api/gitlab/sync/secret')
215-
def gitlab_sync_secret(
216-
authorization: Annotated[str | None, Header()] = None,
217-
image: str | None = None,
218-
):
219122

220-
check_authorization(authorization)
123+
@app.post('/api/github/sync/jwt')
124+
def github_sync_jwt(
125+
authorization: Annotated[str | None, Header()] = None,
126+
image: str | None = None,
127+
cvmfs_repository: str | None = None,
128+
):
129+
github_jwks_keys = get_jwt_keys(
130+
'https://token.actions.githubusercontent.com/.well-known/jwks',
131+
)
221132

222-
if authorization != SECRET_TOKEN:
223-
raise HTTPException(
224-
status_code=401,
225-
detail='Invalid authorization token',
226-
)
133+
check_authorization(authorization)
134+
try:
135+
claims = jwt.decode(
136+
authorization,
137+
github_jwks_keys,
138+
)
139+
except DecodeError:
140+
raise HTTPException(
141+
status_code=403,
142+
detail='Invalid token: DecodeError',
143+
)
144+
except BadSignatureError:
145+
raise HTTPException(
146+
status_code=403,
147+
detail='Invalid token: BadSignatureError',
148+
)
149+
if claims['iss'] != 'https://token.actions.githubusercontent.com':
150+
raise HTTPException(
151+
status_code=403,
152+
detail=f"Invalid issuer {claims['iss']}",
153+
)
227154

228-
request_gitlab_sync(image)
155+
return call_ducc(image, cvmfs_repository)
229156

230157

231-
if expose_api['secret'] and expose_api['github']:
232-
@app.post('/api/github/sync/secret')
233-
def github_sync_secret(
158+
if SECRET_TOKEN is not None:
159+
@app.post('/api/sync/secret')
160+
def gitlab_sync_secret(
234161
authorization: Annotated[str | None, Header()] = None,
235162
image: str | None = None,
163+
cvmfs_repository: str | None = None,
236164
):
237165

238166
check_authorization(authorization)
@@ -243,4 +171,4 @@ def github_sync_secret(
243171
detail='Invalid authorization token',
244172
)
245173

246-
request_github_sync(image)
174+
return call_ducc(image, cvmfs_repository)

0 commit comments

Comments
 (0)