Skip to content

account management: update shadow entries when adding users#2054

Open
stevebeattie wants to merge 2 commits intochainguard-dev:mainfrom
stevebeattie:accounts-update_shadow_entries
Open

account management: update shadow entries when adding users#2054
stevebeattie wants to merge 2 commits intochainguard-dev:mainfrom
stevebeattie:accounts-update_shadow_entries

Conversation

@stevebeattie
Copy link
Member

Currently, when apko is configured to add users and groups to an image, it only adds entries in /etc/passwd and /etc/group, and not corresponding entries in /etc/shadow and /etc/gshadow, despite the added entries being configured to tell the authentication system to look for shadow entries for password information. Fortunately, this is a correctness issue and not a security issue, as at least with the current linux-pam stack, a user with a missing entry in the shadow db is treated as if the account has an invalid password entry, and thus is unable to authenticate.

To address this are two commits in this PR:

  1. Add support for parsing and updating shadow and gshadow files, similar to how passwd and group are handled now, along with tests.
  2. Fix the mutateAccounts() function to also add add entries in shadow/gshadow databases; this adds tests for the previously un-unit-tested mutateAccounts() as well as for the added helper functions. Also, regenerated the golden testdata since this change results in apko generating a different image with the same configuration.

IMPORTANT These changes will cause generated images with the same configuration to be different from images generated before this branch lands.

Ref: https://linear.app/chainguard/issue/PSEC-262/

Detailed commit messages follow:

  1. passwd: add shadow and gshadow file parsing support

    Implements parsing and modification functionality for /etc/shadow and
    /etc/gshadow databases, following the existing patterns from passwd.go
    and group.go.

    Shadow support:

    • Uses *int64 for optional numeric fields to distinguish between empty
      and zero values
    • More restrictive file permissions (0o640)
    • Helper functions for optional field handling

    GShadow support:

    • Parses group administrators and members as string slices
    • Follows GroupFile pattern (no fsys storage in struct)

    Both implementations include comprehensive test coverage with multiple
    filesystem types (MemFS, DirFS), round-trip fidelity tests, edge case
    handling, and error validation.

  2. accounts: fix shadow/gshadow bug and add comprehensive tests

    Fixes bug where users/groups added to /etc/passwd and /etc/group did not
    have corresponding entries created in /etc/shadow and /etc/gshadow.

    Changes to pkg/build/accounts.go:

    • Add userToShadowEntry() to create shadow entries with password "!*"
    • Add groupToGShadowEntry() to create gshadow entries with password "!*"
    • Update mutateAccounts() to create /etc/shadow entries for users
    • Update mutateAccounts() to create /etc/gshadow entries for groups

    New tests in pkg/build/accounts_test.go:

    • Test_userToShadowEntry: verifies shadow entry conversion
    • Test_groupToGShadowEntry: verifies gshadow entry conversion
    • Test_mutateAccounts: integration tests verifying files are created
    • Test_mutateAccounts_emptyConfig: edge case with empty config

    Updates to test golden files:

    • Regenerate golden test images using hack/update_golden.sh to include
      shadow/gshadow files
    • Update hardcoded image hashes in publish_test.go

    All shadow/gshadow entries use "!*" password (locked + invalid hash)
    ensuring secure defaults for newly created accounts.

Steve Beattie and others added 2 commits February 3, 2026 23:26
Implements parsing and modification functionality for /etc/shadow and
/etc/gshadow databases, following the existing patterns from passwd.go
and group.go.

Shadow support:
- Uses *int64 for optional numeric fields to distinguish between empty
  and zero values
- More restrictive file permissions (0o640)
- Helper functions for optional field handling

GShadow support:
- Parses group administrators and members as string slices
- Follows GroupFile pattern (no fsys storage in struct)

Both implementations include comprehensive test coverage with multiple
filesystem types (MemFS, DirFS), round-trip fidelity tests, edge case
handling, and error validation.

Ref: https://linear.app/chainguard/issue/PSEC-262/
Signed-off-by: Steve Beattie <steve.beattie@chainguard.dev>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes bug where users/groups added to /etc/passwd and /etc/group did not
have corresponding entries created in /etc/shadow and /etc/gshadow.

Changes to pkg/build/accounts.go:
- Add userToShadowEntry() to create shadow entries with password "!*"
- Add groupToGShadowEntry() to create gshadow entries with password "!*"
- Update mutateAccounts() to create /etc/shadow entries for users
- Update mutateAccounts() to create /etc/gshadow entries for groups

New tests in pkg/build/accounts_test.go:
- Test_userToShadowEntry: verifies shadow entry conversion
- Test_groupToGShadowEntry: verifies gshadow entry conversion
- Test_mutateAccounts: integration tests verifying files are created
- Test_mutateAccounts_emptyConfig: edge case with empty config

Updates to test golden files:
- Regenerate golden test images using hack/update_golden.sh to include
  shadow/gshadow files
- Update hardcoded image hashes in publish_test.go

All shadow/gshadow entries use "!*" password (locked + invalid hash)
ensuring secure defaults for newly created accounts.

Ref: https://linear.app/chainguard/issue/PSEC-262/
Signed-off-by: Steve Beattie <steve.beattie@chainguard.dev>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Member

@egibs egibs left a comment

Choose a reason for hiding this comment

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

LGTM, appreciate the tests too. Will this have downstream implications for Melange as far as the RunAs functionality is concerned?

@egibs egibs requested review from jdolitsky and wlynch February 4, 2026 13:26
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.

2 participants