winnet
Windows NetAPI and related bindings: local accounts, groups, SMB shares and connections, and domain membership.
This API is VFS-aware: every operation goes through the VFS in scope for the current strand, so it works transparently under remote and elevated Windows contexts.
Domain join
join_domain, unjoin_domain,
rename_machine and
apply_offline_join change how the machine is
identified on the network. Every one of them takes effect only after the
machine is restarted, so a provisioning script must sequence a reboot
before the change is usable. None of them return a status; use
join_status to read the recorded membership.
provision_computer and
apply_offline_join split a join in two: the first
runs where a domain controller is reachable and mints a blob, the second
applies that blob to a Windows installation that has never talked to the
domain. This is the path for image-based and first-boot provisioning, where
the online join would need network, a reachable domain controller and
credentials at exactly the wrong moment.
Types
| Type | Description |
|---|---|
AccountPolicy |
The local password and account-lockout policy. |
Connection |
A connection to a remote SMB resource. |
ConnectionInfo |
A snapshot of an SMB client connection. |
Group |
A Windows local group, identified by immutable SID. |
GroupInfo |
A snapshot of a Windows local group. |
JoinStatus |
The machine's workgroup or domain membership. |
MachineInfo |
Machine identity and server role. |
ServerType |
Native Windows server-role flags. |
Share |
A local SMB share, identified by its immutable name. |
ShareInfo |
A snapshot of a local SMB share. |
User |
A Windows local user, identified by immutable SID. |
UserFlags |
Native Windows user-account flags. |
UserInfo |
A snapshot of a Windows user account's mutable state. |
ConnectionKind |
The kind of resource a network connection reaches. |
ShareKind |
The kind of resource a share exposes. |
ConnectionKind = (:DISK: | :PRINT: | :ANY:)
The kind of resource a network connection reaches.
ShareKind = (:DISKTREE: | :PRINTQ: | :DEVICE: | :IPC:)
The kind of resource a share exposes.
| Symbol | Resource |
|---|---|
:DISKTREE: |
Disk drive |
:PRINTQ: |
Print queue |
:DEVICE: |
Communication device |
:IPC: |
Interprocess communication |
Functions
account_policy() -> AccountPolicy
Reads the local password and lockout policy.
apply_offline_join blob :windows_path …
Applies a provisioning blob to a Windows installation, joining it to the domain without contacting a domain controller.
Takes effect only after the target installation is started or restarted -- see Domain join.
Parameters
| Name | Type | Description |
|---|---|---|
blob |
Bin |
Blob from
provision_computer. |
:windows_path |
fs.Path |
Windows directory of the
installation to modify -- the mounted image's Windows directory for an
offline image, or the running system's own when online is set. |
:online? |
Bool |
The target installation is the running system. |
Example
let blob = fs.Path("ws01.blob").read "b"
winnet.apply_offline_join $blob
windows_path: (fs.windows.Path r"D:\Windows")
connect remote … -> Connection
Connects to a remote SMB resource, optionally redirecting a local device.
With a trailing func the connection is scoped: it is disconnected when
func returns, including when func throws, so a failure partway through
does not leave a mapping behind. Without one the connection is returned and
the caller decides when -- or whether -- to disconnect it.
Connections belong to a logon session. One made under a given account is not visible to a process running as another.
Parameters
| Name | Type | Description |
|---|---|---|
remote |
Str |
Remote resource in UNC form, such as
r"\\server\share". |
:local? |
Str |
Local device to redirect, such as "Z:". |
:user? |
Str |
Account to authenticate as. |
:password? |
Str |
Password for user. |
:kind? |
ConnectionKind |
Resource kind. |
:persistent? |
Bool |
Record the connection so it is restored at logon. |
:save_credentials? |
Bool |
Override whether credentials are saved for the server. |
:persistent
A persistent connection must redirect a local device: Windows only
remembers connections that redirect one. Asking for persistent without
local raises ValueError rather than silently
producing a mapping that disappears at the next logon.
:save_credentials
Supplied credentials are saved for the target server by default when the
connection is persistent, because a restored connection has nothing to
authenticate with otherwise. false suppresses that; true saves them for
a non-persistent connection. Saving requires user.
Saved credentials are per-account, the same way the connection itself is, so a connection provisioned for a service account must be made under that account to be restored for it.
Errors
| Exception | Condition |
|---|---|
ValueError |
persistent requested without local |
sys.AlreadyExistsError |
The local device is already redirected |
sys.PermissionDeniedError |
Credentials were rejected |
sys.NotFoundError |
The remote resource does not exist |
Example
# Scoped: disconnected however the block exits
connect \\build\artifacts local: Z: do |conn|
fs.copy $release $conn.path()
# Unbound: the caller owns teardown
let conn = connect r"\\build\artifacts"
try
publish $conn.remote
finally
conn.disconnect()
# Persistent, surviving a reboot
connect \\build\artifacts
local: Z:
user: r"CORP\ci"
password: $secret
persistent: true
connect[R] remote func … -> R
Connects to a network resource and calls func with the connection, which is
disconnected when func returns.
Parameters
| Name | Type | Description |
|---|---|---|
remote |
Str |
Remote resource in UNC form, such as
r"\\server\share". |
:local? |
Str |
Local device to redirect, such as "Z:". |
:user? |
Str |
Account to authenticate as. |
:password? |
Str |
Password for user. |
:kind? |
ConnectionKind |
Resource kind. |
:persistent? |
Bool |
Record the connection so it is restored at logon. |
:save_credentials? |
Bool |
Override whether credentials are saved for the server. |
func |
((Connection) -> R) |
Called with the Connection. |
connection name_or_info -> Connection
Obtains a handle to an existing connection.
Parameters
| Name | Type | Description |
|---|---|---|
name_or_info |
(Str | ConnectionInfo) |
Local device, remote name, or a prior snapshot. |
connections() -> Iter[ConnectionInfo]
Lists every connection, including ones saved in the profile that are not currently connected.
Example
create_group name … -> Group
Creates a local group.
Parameters
| Name | Type | Description |
|---|---|---|
name |
Str |
Group name. |
:comment? |
Str |
Administrative comment. |
create_share name :path … -> Share
Creates a local SMB share.
Parameters
| Name | Type | Description |
|---|---|---|
name |
Str |
Share name. |
:path |
fs.Path |
Local path to share. |
:kind? |
ShareKind |
Resource kind. Defaults to :DISKTREE:. |
:comment? |
Str |
Comment. |
:max_uses? |
Int |
Connection limit. Defaults to unlimited. |
:special? |
Bool |
Mark the share special. |
:temporary? |
Bool |
Mark the share temporary. |
:sec_desc? |
(security.windows.SecDesc | Bin | Dict[{...}]) |
Security descriptor, self-relative packet, or declarative descriptor. Defaults to the one Windows supplies. |
create_user name :password … -> User
Creates a normal enabled local user.
Parameters
| Name | Type | Description |
|---|---|---|
name |
Str |
Account name. |
:password |
Str |
Initial password. |
:full_name? |
Str |
Display name. |
:comment? |
Str |
Administrative account comment. |
:user_comment? |
Str |
User-facing account comment. |
:home_dir? |
fs.Path |
Home directory. |
:home_dir_drive? |
Str |
Drive designator assigned to the home directory
at logon, such as "Z:". |
:profile? |
fs.Path |
Profile path. |
:script_path? |
fs.Path |
Logon script path. |
:account_expires? |
(time.DateTime | nil) |
Expiration instant. nil means
the account never expires. |
:disabled? |
Bool |
Whether the account is disabled. |
:password_never_expires? |
Bool |
Whether the password is exempt from expiry. |
:password_cannot_change? |
Bool |
Whether the user may change the password. |
Example
let user = create_user build-user password: $password
full_name: "Build User"
comment: "Automation account"
disabled: true
password_never_expires: true
group principal -> Group
Obtains a handle to an existing local group.
Parameters
| Name | Type | Description |
|---|---|---|
principal |
(Str | security.windows.Sid | GroupInfo) |
Group name, SID, or a prior snapshot. |
groups() -> Iter[GroupInfo]
Lists local groups.
join_domain domain …
Joins the machine to a domain.
Takes effect only after a restart -- see Domain join.
Supply either account and password or machine_password; the two are
mutually exclusive, because joining with a pre-created computer account
password leaves no room for a user account.
Parameters
| Name | Type | Description |
|---|---|---|
domain |
Str |
Domain to join. |
:ou? |
Str |
Organizational unit for the computer account. |
:account? |
Str |
Domain account authorized to join, such as
"CORP\\joiner". Must be given together with password; omit both to use
the caller's own credentials. |
:password? |
Str |
Password for account. |
:machine_password? |
Str |
Password of a pre-created computer account, used
instead of account and password. |
:create_account? |
Bool |
Create the computer account as part of the join. |
:join_if_joined? |
Bool |
Proceed even if already joined to a domain. |
:unsecure? |
Bool |
Perform an unsecured join. |
:defer_spn? |
Bool |
Defer setting the service principal name until a later rename. |
:force_spn? |
Bool |
Force the service principal name to be set. |
:dc_account? |
Bool |
Join using a domain controller account. |
:with_new_name? |
Bool |
Join under a rename that has not taken effect yet. |
:readonly? |
Bool |
Join against a read-only domain controller. |
:ambiguous_dc? |
Bool |
Allow an ambiguous domain controller name. |
:no_netlogon_cache? |
Bool |
Do not write the netlogon cache. |
:no_account_reuse? |
Bool |
Fail rather than reuse an existing computer account. |
Errors
| Exception | Condition |
|---|---|
sys.AlreadyExistsError |
Already joined and join_if_joined was not set |
sys.InvalidInputError |
Credentials are incomplete, or both credential forms given |
sys.PermissionDeniedError |
Caller may not join the machine to the domain |
Example
winnet.join_domain corp.example.com
ou: "OU=Servers,DC=corp,DC=example,DC=com"
account: r"CORP\joiner"
password: $password
create_account: true
echo "restart to complete the join"
join_status() -> JoinStatus
Reads the machine's current workgroup or domain membership.
machine_info() -> MachineInfo
Reads the computer name, domain membership, OS level and server role.
provision_computer domain :machine … -> Bin
Creates a computer account in the domain and returns the blob that joins a machine to it.
Run this where a domain controller is reachable, then apply the blob with
apply_offline_join.
The blob contains the computer account password. Treat it as a secret: anyone holding it can join a machine as that account.
Parameters
| Name | Type | Description |
|---|---|---|
domain |
Str |
Domain to create the computer account in. |
:machine |
Str |
Computer name to provision. |
:ou? |
Str |
Organizational unit for the computer account. |
:dc? |
Str |
Domain controller to provision against. |
:reuse? |
Bool |
Reuse an existing computer account. |
:default_password? |
Bool |
Use the default computer account password. |
:skip_account_search? |
Bool |
Skip searching for an existing account. |
:root_ca_certs? |
Bool |
Include root CA certificates in the blob. |
:downlevel_priv_support? |
Bool |
Support provisioning by a down-level privileged user. |
Example
let blob = winnet.provision_computer corp.example.com
machine: WS01
ou: "OU=Workstations,DC=corp,DC=example,DC=com"
fs.Path("ws01.blob").write $blob
rename_machine name …
Renames the machine within its domain.
Takes effect only after a restart -- see Domain join.
Parameters
| Name | Type | Description |
|---|---|---|
name |
Str |
New computer name. |
:account? |
Str |
Domain account authorized to rename. Must be
given together with password; omit both to use the caller's own
credentials. |
:password? |
Str |
Password for account. |
:create_account? |
Bool |
Create the renamed computer account if it is missing. |
share name_or_info -> Share
Obtains a handle to an existing local SMB share.
Parameters
| Name | Type | Description |
|---|---|---|
name_or_info |
(Str | ShareInfo) |
Share name or a prior snapshot. |
shares() -> Iter[ShareInfo]
Lists every local SMB share, administrative and non-disk shares included.
universal_name path -> Str
Resolves a path on a redirected device to its UNC form.
Parameters
| Name | Type | Description |
|---|---|---|
path |
fs.Path |
Path on a redirected device. |
Example
unjoin_domain …
Removes the machine from its domain.
Takes effect only after a restart -- see Domain join.
Parameters
| Name | Type | Description |
|---|---|---|
:account? |
Str |
Domain account authorized to unjoin. Must be
given together with password; omit both to use the caller's own
credentials. |
:password? |
Str |
Password for account. |
:delete_account? |
Bool |
Disable the computer account in the domain. |
Errors
| Exception | Condition |
|---|---|
sys.NotFoundError |
The machine is not joined to a domain |
sys.InvalidInputError |
The machine is a domain controller |
sys.PermissionDeniedError |
Caller may not unjoin the machine |
update_account_policy … -> AccountPolicy
Updates the supplied local password and lockout settings.
Omitted settings are left unchanged.
Parameters
| Name | Type | Description |
|---|---|---|
:min_password_length? |
Int |
Minimum password length. |
:max_password_age? |
(time.Duration | nil) |
Maximum password age. nil
selects no limit, so passwords never expire. |
:min_password_age? |
time.Duration |
Minimum password age. |
:force_logoff? |
(time.Duration | nil) |
Forced-logoff delay. nil
disables forced logoff. |
:password_history_length? |
Int |
Number of prior passwords retained. |
:lockout_duration? |
time.Duration |
Account lockout duration. |
:lockout_observation_window? |
time.Duration |
Failed-logon counter observation window. |
:lockout_threshold? |
Int |
Failed logons allowed before lockout. Zero disables lockout. |
Returns
The resulting policy.
user principal -> User
Obtains a handle to an existing local user.
Parameters
| Name | Type | Description |
|---|---|---|
principal |
(Str | security.windows.Sid | UserInfo) |
Account name, SID, or a prior snapshot. |
users() -> Iter[UserInfo]
Lists local user accounts.