Skip to content

Add wslc login, wslc logout, and wslc push commands for registry authentication#40173

Open
kvega005 wants to merge 101 commits intomicrosoft:feature/wsl-for-appsfrom
kvega005:user/kevinve/wslc-login
Open

Add wslc login, wslc logout, and wslc push commands for registry authentication#40173
kvega005 wants to merge 101 commits intomicrosoft:feature/wsl-for-appsfrom
kvega005:user/kevinve/wslc-login

Conversation

@kvega005
Copy link
Copy Markdown

@kvega005 kvega005 commented Apr 13, 2026

Summary of the Pull Request

Adds wslc login, wslc logout, and wslc image push commands, enabling authenticated container registry workflows in wslc.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

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)

  • Two backends, configurable via credentialStore in wslc user settings:
    • WinCred (default): Uses Windows Credential Manager with a wslc-credential/ target name prefix to isolate wslc entries from other applications.
    • File: DPAPI-encrypted JSON file at %LocalAppData%\wslc\registry-credentials.json with retry logic for concurrent access (sharing violation handling).
  • Stored credentials are automatically passed to PullImage and PushImage API calls based on the image's registry domain.

Auth Integration

  • ImageService::Pull and ImageService::Push extract the registry domain from the image reference and look up stored credentials before calling the session API.
  • Authenticate delegates to the session's Docker engine and supports both identity token and username/password auth header formats.

Validation Steps Performed

  • E2E tests against a local htpasswd-authenticated registry container:
    • Push/pull succeed after login, fail before login and after logout.
    • Interactive login, -u/-p flag login, and --password-stdin login all verified.
    • Mutual exclusivity and missing-username validation tested.
  • Push/pull against an unauthenticated local registry verified.
  • Help output tests for all new commands and root aliases.
  • Negative path tests: push/pull of non-existent images, double logout.

Copilot AI review requested due to automatic review settings April 15, 2026 20:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 at src/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 rename PullImageCallback.{h,cpp} to ImageProgressCallback.{h,cpp} and update build files, or keep the file name and include PullImageCallback.h while using the new ImageProgressCallback class name inside it.
    src/windows/wslc/tasks/RegistryTasks.h:1
  • This using declaration is at global header scope, which can unintentionally leak the alias into any includer and increase the chance of name collisions. Prefer moving it inside namespace wsl::windows::wslc::task { ... } or removing it and using the fully-qualified name in declarations.

Comment on lines +71 to +72
THROW_WIN32_IF(_doserrno, err != 0);

Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_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.

Suggested change
THROW_WIN32_IF(_doserrno, err != 0);
if (err != 0)
{
auto dosError = _doserrno;
if (dosError != 0)
{
THROW_WIN32(dosError);
}
THROW_HR(HRESULT_FROM_WIN32(err));
}

Copilot uses AI. Check for mistakes.
Comment thread src/windows/wslc/services/FileCredStorage.cpp Outdated
Comment thread src/windows/common/wslutil.cpp Outdated
Copilot AI review requested due to automatic review settings April 15, 2026 22:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 50 out of 52 changed files in this pull request and generated 2 comments.

Comment thread test/windows/wslc/WSLCCLICredStorageUnitTests.cpp
Comment thread test/windows/wslc/e2e/WSLCE2EHelpers.h
Copilot AI review requested due to automatic review settings April 15, 2026 23:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 52 out of 53 changed files in this pull request and generated 5 comments.

Comment thread test/windows/wslc/e2e/WSLCE2EPushPullTests.cpp Outdated
Comment thread src/windows/wslc/services/WinCredStorage.cpp
Comment thread src/windows/wslc/services/FileCredStorage.cpp
Comment thread test/windows/Common.cpp Outdated
Comment thread test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp Outdated
Copilot AI review requested due to automatic review settings April 16, 2026 01:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  • BuildRegistryAuthHeader no longer includes the serveraddress field in the JSON payload. The Docker Engine X-Registry-Auth schema commonly includes serveraddress, and this repo already models serveraddress as part of docker auth JSON (see docker_schema::AuthRequest). Dropping it risks compatibility regressions with registries/daemons that require or expect the field. Consider restoring serveraddress in the encoded JSON (and passing the server address down from callers) to preserve prior behavior/interop.

Comment thread src/windows/wslc/services/RegistryService.cpp
Copilot AI review requested due to automatic review settings April 16, 2026 02:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

THROW_WIN32_IF(dosError, dosError != 0);
THROW_HR(E_FAIL);
}

Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
fd.release();

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +43
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);
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants