From 0b6d7eea85d540f4d93c158d971c61f979cf9e8b Mon Sep 17 00:00:00 2001 From: Alexander Jung Date: Fri, 3 Apr 2026 12:48:56 +0000 Subject: [PATCH 1/2] fix(build): Allow returning credentials with no metros In the scenario we do NOT have any metros (registries) set, just return the credentials of the organization directly. Signed-off-by: Alexander Jung --- internal/images/resolver.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/images/resolver.go b/internal/images/resolver.go index 06e45bb1..41327b90 100644 --- a/internal/images/resolver.go +++ b/internal/images/resolver.go @@ -139,6 +139,18 @@ func hostCreds(profile *config.Profile, hostname string) (string, string, error) if slices.Contains(defaultRegistries, hostname) { return decodeAuth(profile.Token) } + + if len(profile.Metros) == 0 { + username := profile.Organization + if username == "" { + // organization may not be set on old or manually created + // profiles - so fall back to decoding the username from the + // token itself + username, _, _ = decodeAuth(profile.Token) + } + return username, profile.Token, nil + } + for _, metro := range profile.Metros { if hostname == metro.Index().Host { username := profile.Organization From 0b9943d52deaacb73ba9310f3e20cbfdbd5ba788 Mon Sep 17 00:00:00 2001 From: Alexander Jung Date: Fri, 3 Apr 2026 12:50:44 +0000 Subject: [PATCH 2/2] feat: Add `--no-tls-verify` to `build` subcommand Signed-off-by: Alexander Jung --- internal/cmd/build.go | 13 ++++++++----- internal/images/images.go | 24 ++++++++++++++++++++++-- internal/images/resolver.go | 5 ++++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/internal/cmd/build.go b/internal/cmd/build.go index 2e5c9d88..4703f0c9 100644 --- a/internal/cmd/build.go +++ b/internal/cmd/build.go @@ -24,10 +24,11 @@ type BuildCmd struct { Output string `short:"o" help:"Output destination"` // similar to docker compose build - BuildArg []string `help:"Set build-time variables."` - NoCache bool `help:"Do not use cache when building the image."` - Secret []string `help:"Secret to expose to the build (format: \"id=mysecret[,src=/local/secret]\")."` - SSH []string `help:"SSH agent socket or keys to expose to the build (format: \"default|[=|[,]]\")."` + BuildArg []string `help:"Set build-time variables."` + NoCache bool `help:"Do not use cache when building the image."` + NoTLSVerify bool `help:"Skip TLS certificate verification when pushing to a registry."` + Secret []string `help:"Secret to expose to the build (format: \"id=mysecret[,src=/local/secret]\")."` + SSH []string `help:"SSH agent socket or keys to expose to the build (format: \"default|[=|[,]]\")."` } func (BuildCmd) Examples() []kingkong.Example { @@ -134,7 +135,9 @@ func (c *BuildCmd) Run(ctx context.Context, cfg *config.Config) error { return err } - access, err := images.Accessor(ctx) + access, err := images.Accessor(ctx, + images.WithSkipTLSVerify(c.NoTLSVerify), + ) if err != nil { return err } diff --git a/internal/images/images.go b/internal/images/images.go index a58b7dc0..3a65f562 100644 --- a/internal/images/images.go +++ b/internal/images/images.go @@ -23,7 +23,27 @@ var defaultRegistries = []string{ "index.unikraft.io", } -func Accessor(ctx context.Context) (*imagespec.Accessor, error) { +// AccessorOpt is a functional option for configuring an Accessor. +type AccessorOpt func(*accessorOpts) + +type accessorOpts struct { + skipTLSVerify bool +} + +// WithSkipTLSVerify configures the accessor to skip TLS certificate +// verification when communicating with registries. +func WithSkipTLSVerify(skip bool) AccessorOpt { + return func(o *accessorOpts) { + o.skipTLSVerify = skip + } +} + +func Accessor(ctx context.Context, opts ...AccessorOpt) (*imagespec.Accessor, error) { + var o accessorOpts + for _, opt := range opts { + opt(&o) + } + cfg := config.FromContextOrDefault(ctx) profile, err := cfg.CurrentProfile() if err != nil { @@ -31,7 +51,7 @@ func Accessor(ctx context.Context) (*imagespec.Accessor, error) { } return imagespec.NewAccessor( - imagespec.WithResolver(Resolver(profile)), + imagespec.WithResolver(Resolver(profile, o.skipTLSVerify)), imagespec.WithReferenceParser(ParseNormalizedNamed), ), nil } diff --git a/internal/images/resolver.go b/internal/images/resolver.go index 41327b90..9eaf58b0 100644 --- a/internal/images/resolver.go +++ b/internal/images/resolver.go @@ -22,7 +22,7 @@ import ( "unikraft.com/cli/internal/version" ) -func Resolver(profile *config.Profile) remotes.Resolver { +func Resolver(profile *config.Profile, skipTLSVerify bool) remotes.Resolver { headers := http.Header{} headers.Set("User-Agent", version.UserAgent()) @@ -43,6 +43,9 @@ func Resolver(profile *config.Profile) remotes.Resolver { return false, nil } insecureHost := func(host string) (bool, error) { + if skipTLSVerify { + return true, nil + } for _, index := range indexes { if host == index.Host { return index.Insecure, nil