Add wslc login, wslc logout, and wslc push commands for registry authentication#40173
Add wslc login, wslc logout, and wslc push commands for registry authentication#40173kvega005 wants to merge 101 commits intomicrosoft:feature/wsl-for-appsfrom
wslc login, wslc logout, and wslc push commands for registry authentication#40173Conversation
… into user/kevinve/registry
… into user/kevinve/registry
… into user/kevinve/registry
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 50 out of 52 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
src/windows/wslc/tasks/ImageTasks.cpp:1
- The diff changes includes across the codebase to
ImageProgressCallback.h, but the callback header shown in this PR is still atsrc/windows/wslc/services/PullImageCallback.h(and likewise the.cpp). As-is, this will fail to build unless the file was actually renamed (and CMake/source lists updated accordingly). Either renamePullImageCallback.{h,cpp}toImageProgressCallback.{h,cpp}and update build files, or keep the file name and includePullImageCallback.hwhile using the newImageProgressCallbackclass name inside it.
src/windows/wslc/tasks/RegistryTasks.h:1 - This
usingdeclaration is at global header scope, which can unintentionally leak the alias into any includer and increase the chance of name collisions. Prefer moving it insidenamespace wsl::windows::wslc::task { ... }or removing it and using the fully-qualified name in declarations.
| THROW_WIN32_IF(_doserrno, err != 0); | ||
|
|
There was a problem hiding this comment.
_wsopen_s returns an errno_t in err (CRT errno-style), while _doserrno may be 0 for some failures. Using THROW_WIN32_IF(_doserrno, err != 0) can throw with error=0 or otherwise mis-report the failure cause. Prefer throwing based on err when nonzero, and only use _doserrno when it is set (or translate err appropriately) so that failures are surfaced reliably.
| THROW_WIN32_IF(_doserrno, err != 0); | |
| if (err != 0) | |
| { | |
| auto dosError = _doserrno; | |
| if (dosError != 0) | |
| { | |
| THROW_WIN32(dosError); | |
| } | |
| THROW_HR(HRESULT_FROM_WIN32(err)); | |
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 42 out of 43 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/windows/common/wslutil.cpp:1523
BuildRegistryAuthHeaderno longer includes theserveraddressfield in the JSON payload. The Docker Engine X-Registry-Auth schema commonly includesserveraddress, and this repo already modelsserveraddressas part of docker auth JSON (seedocker_schema::AuthRequest). Dropping it risks compatibility regressions with registries/daemons that require or expect the field. Consider restoringserveraddressin the encoded JSON (and passing the server address down from callers) to preserve prior behavior/interop.
| THROW_WIN32_IF(dosError, dosError != 0); | ||
| THROW_HR(E_FAIL); | ||
| } | ||
|
|
There was a problem hiding this comment.
CreateFileExclusive wraps the fd in a UniqueFd and then also wraps the same underlying handle in a wil::unique_file via _fdopen(fd.get(), ...). Because the UniqueFd is never released, both UniqueFd and wil::unique_file will close the same descriptor, which can lead to a double-close (and potentially closing an unrelated descriptor if the fd value gets reused). After _fdopen succeeds, release ownership from UniqueFd (or construct the FILE* in a way that transfers ownership) so the descriptor is closed exactly once.
| fd.release(); |
| static void TestStoreAndGetRoundTrips(ICredentialStorage& storage) | ||
| { | ||
| auto cleanup = wil::scope_exit([&]() { storage.Erase("wslc-test-server1"); }); | ||
| storage.Store("wslc-test-server1", "test-user", "credential-data-1"); | ||
|
|
||
| auto [username, secret] = storage.Get("wslc-test-server1"); | ||
| VERIFY_ARE_EQUAL(std::string("test-user"), username); | ||
| VERIFY_ARE_EQUAL(std::string("credential-data-1"), secret); | ||
| } |
There was a problem hiding this comment.
The wil::scope_exit cleanup lambdas call storage.Erase(...), which throws on failure (including E_NOT_SET for missing entries). wil::scope_exit is noexcept and will fail-fast if the lambda throws, so a cleanup-path error can terminate the whole test process. Wrap the erase in a non-throwing cleanup (catch and log/ignore), or use a logging/noexcept scope-exit helper so test failures don’t become process termination.
Summary of the Pull Request
Adds
wslc login,wslc logout, andwslc image pushcommands, enabling authenticated container registry workflows in wslc.PR Checklist
Detailed Description of the Pull Request / Additional comments
New Commands
wslc login [-u <user>] [-p <pass>] [--password-stdin] [<server>]— Authenticates with a container registry and stores credentials for subsequent push/pull operations. Supports interactive prompts, inline flags, and piped password input. Defaults to Docker Hub when no server is specified.wslc logout [<server>]— Removes stored credentials for a registry.wslc image push <image>— Pushes a local image to a registry, automatically using stored credentials when available.wslc registry— Parent command group for login/logout. All three commands are also available as root-level aliases (wslc login,wslc logout,wslc push).Credential Storage (
RegistryService)credentialStorein wslc user settings:wslc-credential/target name prefix to isolate wslc entries from other applications.%LocalAppData%\wslc\registry-credentials.jsonwith retry logic for concurrent access (sharing violation handling).PullImageandPushImageAPI calls based on the image's registry domain.Auth Integration
ImageService::PullandImageService::Pushextract the registry domain from the image reference and look up stored credentials before calling the session API.Authenticatedelegates to the session's Docker engine and supports both identity token and username/password auth header formats.Validation Steps Performed
-u/-pflag login, and--password-stdinlogin all verified.