Skip to content

Commit 56a9724

Browse files
authored
Merge pull request #1724 from manics/registry-dynamic-token-2
Support dynamic push credentials obtained from registry
2 parents bec74d4 + cb6d328 commit 56a9724

File tree

3 files changed

+69
-14
lines changed

3 files changed

+69
-14
lines changed

binderhub/build.py

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,21 @@ class BuildExecutor(LoggingConfigurable):
8787

8888
push_secret = Unicode(
8989
"",
90-
help="Implementation dependent secret for pushing image to a registry.",
90+
help="Implementation dependent static secret for pushing image to a registry.",
91+
config=True,
92+
)
93+
94+
registry_credentials = Dict(
95+
{},
96+
help=(
97+
"Implementation dependent credentials for pushing image to a registry. "
98+
"For example, if push tokens are temporary this could be used to pass "
99+
"dynamically created credentials "
100+
'`{"registry": "docker.io", "username":"user", "password":"password"}`. '
101+
"This will be JSON encoded and passed in the environment variable "
102+
"CONTAINER_ENGINE_REGISTRY_CREDENTIALS` to repo2docker. "
103+
"If provided this will be used instead of push_secret."
104+
),
91105
config=True,
92106
)
93107

@@ -231,7 +245,26 @@ def _default_api(self):
231245
# Overrides the default for BuildExecutor
232246
push_secret = Unicode(
233247
"binder-build-docker-config",
234-
help="Implementation dependent secret for pushing image to a registry.",
248+
help=(
249+
"Name of a Kubernetes secret containing static credentials for pushing "
250+
"an image to a registry."
251+
),
252+
config=True,
253+
)
254+
255+
registry_credentials = Dict(
256+
{},
257+
help=(
258+
"Implementation dependent credentials for pushing image to a registry. "
259+
"For example, if push tokens are temporary this could be used to pass "
260+
"dynamically created credentials "
261+
'`{"registry": "docker.io", "username":"user", "password":"password"}`. '
262+
"This will be JSON encoded and passed in the environment variable "
263+
"CONTAINER_ENGINE_REGISTRY_CREDENTIALS` to repo2docker. "
264+
"If provided this will be used instead of push_secret. "
265+
"Currently this is passed to the build pod as a plain text environment "
266+
"variable, though future implementations may use a Kubernetes secret."
267+
),
235268
config=True,
236269
)
237270

@@ -394,7 +427,23 @@ def submit(self):
394427
)
395428
]
396429

397-
if self.push_secret:
430+
env = [
431+
client.V1EnvVar(name=key, value=value)
432+
for key, value in self.extra_envs.items()
433+
]
434+
if self.git_credentials:
435+
env.append(
436+
client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials)
437+
)
438+
439+
if self.registry_credentials:
440+
env.append(
441+
client.V1EnvVar(
442+
name="CONTAINER_ENGINE_REGISTRY_CREDENTIALS",
443+
value=json.dumps(self.registry_credentials),
444+
)
445+
)
446+
elif self.push_secret:
398447
volume_mounts.append(
399448
client.V1VolumeMount(mount_path="/root/.docker", name="docker-config")
400449
)
@@ -405,15 +454,6 @@ def submit(self):
405454
)
406455
)
407456

408-
env = [
409-
client.V1EnvVar(name=key, value=value)
410-
for key, value in self.extra_envs.items()
411-
]
412-
if self.git_credentials:
413-
env.append(
414-
client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials)
415-
)
416-
417457
self.pod = client.V1Pod(
418458
metadata=client.V1ObjectMeta(
419459
name=self.name,

binderhub/builder.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,12 @@ async def get(self, provider_prefix, _unescaped_spec):
381381
.lower()
382382
)
383383

384+
image_without_tag, image_tag = _get_image_basename_and_tag(image_name)
384385
if self.settings["use_registry"]:
385386
for _ in range(3):
386387
try:
387388
image_manifest = await self.registry.get_image_manifest(
388-
*_get_image_basename_and_tag(image_name)
389+
image_without_tag, image_tag
389390
)
390391
image_found = bool(image_manifest)
391392
break
@@ -457,7 +458,13 @@ async def get(self, provider_prefix, _unescaped_spec):
457458
image_name=image_name,
458459
git_credentials=provider.git_credentials,
459460
)
460-
if not self.settings["use_registry"]:
461+
if self.settings["use_registry"]:
462+
push_token = await self.registry.get_credentials(
463+
image_without_tag, image_tag
464+
)
465+
if push_token:
466+
build.registry_credentials = push_token
467+
else:
461468
build.push_secret = ""
462469

463470
self.build = build

binderhub/registry.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ async def get_image_manifest(self, image, tag):
329329
raise
330330
return json.loads(resp.body.decode("utf-8"))
331331

332+
async def get_credentials(self, image, tag):
333+
"""
334+
If a dynamic token is required for pushing an image to the registry
335+
return a dictionary of login credentials, otherwise return None
336+
(caller should get credentials from some other source)
337+
"""
338+
return None
339+
332340

333341
class FakeRegistry(DockerRegistry):
334342
"""

0 commit comments

Comments
 (0)