Repository navigation
feat(pro): packages upload to SMB file share distribution points - #462
Open
neilmartin83 wants to merge 7 commits into
Open
neilmartin83 wants to merge 7 commits into
neilmartin83 wants to merge 7 commits into
Conversation
…oint `pro packages upload --distribution-point <name>` copies a package to the Packages folder of an SMB2/3 file share distribution point, through hirochachacha/go-smb2/v2 (pure Go, so CGO_ENABLED=0 cross-builds are unchanged). With no flag, a tenant with no cloud distribution point uses its master SMB distribution point. AFP and any unrecognised connection type are refused, never selected. Jamf Pro never returns the share account's password, so it comes from, in order: JAMFSMB_USERNAME/JAMFSMB_PASSWORD, the account saved in the profile by the new `pro packages smb-setup` (password in the keychain, only a reference in the config), a Kerberos ticket in a FILE cache (KRB5CCNAME, else /tmp/krb5cc_<uid>), then a prompt on a terminal. No credential flag exists, and --no-input fails with a hint rather than prompting. smb-setup is refused over MCP. The account, share and Packages folder are checked before the package record is created. The file is written under a temporary name and renamed into place. Jamf Pro computes no hash for a file share, so the check is the size on the share. Tested against Samba; not against Windows or a KDC. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…cket A bound Mac, NoMAD or Jamf Connect keeps its ticket in the system's API credential cache, which the SMB client cannot read. With no password supplied or saved and KRB5CCNAME unset, copy the ticket-granting ticket to a private 0700/0600 file with the system's own kcc, take the realm from klist, and use the system krb5.conf (else one generated from the realm with dns_lookup_kdc). The copy is removed when the upload ends. Nothing found is not an error. Tested against a Samba AD DC: the Kerberos path on Linux end to end, and on macOS the real kcc/klist copy loaded by the SMB client's Kerberos reader. The macOS discovery was not run against a full SMB session, nor against a real DNS SRV lookup of a KDC. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A multi-gigabyte package used to copy in silence. The SMB, JCDS and API routes now report bytes sent to stderr: one line redrawn in place on a terminal, a line per quarter anywhere else, nothing under --quiet. --no-hints leaves it on, since it is progress and not a hint. The JCDS transfer sizes its parts from the file's length and reads them through Seek and ReadAt, so the file is wrapped by embedding rather than by a plain reader. The count is held at the total, because a part read again after a failed attempt would otherwise report past 100%, and a rewind for an HTTP 429 retry resets it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…on an instance profile With no --distribution-point, a tenant with no cloud distribution point falls back to its master SMB distribution point. That fallback only ran when the cloud distribution point could be read through the Platform SDK, which an instance (OAuth or token) profile does not have, so those profiles went to the API upload endpoint, created a package record, and polled for a hash that never came. Read /v1/cloud-distribution-point over the profile's own client for that case. Only an explicit NONE counts; a failed or unprivileged read stays silent and takes the API route as before. The no-cloud-DP refusal now also names --distribution-point. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…n SMB share The generated delete removes the package record only, which leaves the binary orphaned on a file share distribution point. Both commands now take --distribution-point and select the share by the upload's rule (named, else the master SMB distribution point when the tenant has no cloud distribution point). The share is checked before any record is deleted. A file is removed only for a record that reads back 404 afterwards, so a bulk delete that fails part way leaves the files of the surviving records alone. A file already absent from the share is reported, not an error. A krb5.conf go-krb5 cannot split (a one-line realm block) panicked inside NewKerberosCredential; it is now an error naming the file. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Each file goes through the single upload, so the route, the verification and the record handling are unchanged. The SMB share and its account are resolved and preflighted once, so a prompted account is asked for once and a wrong one stops the run before a record exists. A failed file does not stop the rest; the run exits non-zero and names each failure. A named --distribution-point on a tenant with no cloud distribution point was refused by the cloud-distribution-point check before the share was used; an explicit share now bypasses it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
pro packages uploadcan now write to a Classic SMB file share distribution point, not only to JCDS or through the Jamf Pro upload endpoint (which only reaches a cloud DP).--distribution-point <name>picks the DP. With no flag, a tenant with no cloud DP uses its master SMB DP (it used to be refused), on gateway and instance profiles alike. A tenant that has JCDS and a master file share still uploads to JCDS; name the share to override. AFP and any unrecognisedconnection_typeare refused, never selected.<share>/Packages/<file>(Jamf's documented layout), written under a temporary name and renamed into place. A share with noPackagesfolder is refused rather than having one created.--quiet.Delete and multi-file
pro packages deleteanddelete-multipletake--distribution-pointand, on an SMB share, remove the package file as well as the record. The generated delete removes the record only, so the binary was left on a share Jamf Pro never cleans. The share is chosen by the upload's rule (named, else the master SMB DP when the tenant has no cloud DP) and the account is resolved the same way. The generated commands are untouched: a wrapper reads each record's file name first, checks the share before any record is deleted, lets the generated command run (ids,--name,--from-file,--ids, stdin, confirmation, cooldown), then removes the file of every record that now reads back 404. A bulk delete that fails part way leaves the files of the surviving records alone. A file already absent from the share is reported, not an error; a file that cannot be removed after its record is gone exits non-zero and names the file.--dry-runlists the files that would go.pro packages upload-multiple <file>...uploads several files through the single upload (same route, same verification). The share and its account are resolved and checked once, so a prompted account is asked for once and a wrong one stops the run before any record exists. Every file is checked first, and two files with the same name (case-insensitive) are refused. A failed file does not stop the rest; the run exits non-zero and names each failure (--allow-partial-failuredowngrades it). With several files, each record is printed as its own JSON document.--distribution-pointon a tenant whose cloud DP isNONEwas refused by the cloud-DP check before the named share was used. An explicit share now bypasses it.krb5.confgo-krb5 cannot split (a realm block on one line) panicked inside the client; it is now an error naming the file.Credentials
Jamf Pro never returns the DP account's password, so it comes from, in order:
JAMFSMB_USERNAME/JAMFSMB_PASSWORD(CI)pro packages smb-setup(password in the keychain, only akeychain:reference in the profile'ssmb-credentials)KRB5CCNAME, else/tmp/krb5cc_<uid>, else on macOS a private0600copy of the signed-in user's ticket viakcc copy_cred_cache(removed after the upload)No credential flag exists, nothing is read from stdin, and
smb-setupalways prompts, proves the account before saving, and is refused over MCP. The account, share andPackagesfolder are checked before the package record is created.Dependency
github.com/hirochachacha/go-smb2/v2, pure Go (CGO_ENABLED=0cross-builds unchanged). It is an untagged pseudo-version: upstreammasteris the/v2module but has no tag. I asked upstream for one in hirochachacha/go-smb2#110. v1.1.0 has no Kerberos. I also looked atjfjallid/go-smband rejected it (a security-tooling module that depends on several personal forks).Tested
Packagesfolder, no record left behind on any pre-flight failure.JAMFSMB_*, exits 2 with a hint without.FILE:cache; on macOS the realkcc/klistcopy loaded by the SMB client's Kerberos reader.smb-setupthrough a pty: wrong password refused, save, upload from the saved account,--remove.-raceon the progress code.NONE, a master SMB DP exists): found the DP and went to SMB, with no package record created before the connection check. Found by testing: before c25cfe9 only gateway profiles could read the cloud DP, so instance profiles went to the API route and polled for a hash that never came.v1.35.0tag (jamf-cli-internal) builds this branch.delete-multiple(--idsand stdin) andupload-multipleagainst Samba on a real tenant, on an instance profile and a gateway profile: NTLM both, Kerberos fordeleteon both (cifs/localhostagainst a Samba AD DC). Also:--from-filewith an id and a name, wrong password leaves the record, file already absent from the share, a cloud DP present with no flag (record only), re-upload without--yesfailing per file, dry-run. Not run: Kerberos fordelete-multipleandupload-multiple, which share the auth path.make fmt,golangci-lint,go fix,lint-dead,verify-generated,verify-site-output,go test ./internal/....Not tested
Windows as SMB server or KDC; NoMAD and Jamf Connect specifically; a full SMB session from macOS with Kerberos; the generated
krb5.confwith DNS SRV KDC lookup.Notes
🤖 Generated with Claude Code