Compare commits
73 Commits
Windows10
...
UbuntuServ
Author | SHA1 | Date | |
---|---|---|---|
d29f7b3223 | |||
bd82e13fc4 | |||
2f902fa27c | |||
37ecd4a1b9 | |||
8a8cb09984 | |||
bc46b09708 | |||
d508b28213 | |||
03ed59680f | |||
40ade38c78 | |||
c89edd3ee9 | |||
e5880c222e | |||
236db40016 | |||
b340c777ba | |||
10624f8c90 | |||
eca6ae515e | |||
b6656c3d9c | |||
82b8eeca4f | |||
5af4d729ef | |||
73c266632c | |||
cd448a0af3 | |||
6b1db0dd23 | |||
f15485e7c2 | |||
4257849ca4 | |||
3426cd7ed3 | |||
226fa9859b | |||
7e36abe0cb | |||
1e470f38dd | |||
389c35bb05 | |||
f40889370d | |||
990534618b | |||
c0953acefe | |||
b33280b443 | |||
9460bc9bd6 | |||
5f835960b9 | |||
35c2df5f4e | |||
fcdc7d07ad | |||
998f5ef381 | |||
a9041b19a4 | |||
0a2647d465 | |||
93cadce4fe | |||
4d7400ed43 | |||
f8d0c1cdde | |||
4ea138fd69 | |||
d5c3e2c0b6 | |||
f33a99ad05 | |||
d50bf402af | |||
8adbec57d5 | |||
06d0a44c4d | |||
be9609875a | |||
6c27d2e74d | |||
346b2878a6 | |||
0ff31c104b | |||
4bf036c49d | |||
f6a27db822 | |||
b9fb3cdb30 | |||
d95daa1861 | |||
fcea2ef449 | |||
d680b0dde4 | |||
03b5338f59 | |||
b7d737e7df | |||
c4389f4932 | |||
bfa31fd7f7 | |||
94e1624180 | |||
64ecc33dcb | |||
1da7269d87 | |||
50bef57ff7 | |||
66e3c01863 | |||
7b525a6ea8 | |||
6ae9003fec | |||
7557a7bfca | |||
5501c640fc | |||
3f0a8ca3c4 | |||
04c9eb4f03 |
31
.drone.yml
31
.drone.yml
@ -16,52 +16,51 @@ steps:
|
||||
commands:
|
||||
- yamllint --version
|
||||
- packer --version
|
||||
- pwsh --version
|
||||
- ansible --version
|
||||
- ovftool --version
|
||||
- name: Windows 10
|
||||
- name: Ubuntu Server 20.04
|
||||
image: bv11-cr01.bessems.eu/library/packer-extended
|
||||
pull: always
|
||||
commands:
|
||||
- sed -i -e "s/<<img-productkey>>/$${PRODUCTKEY}/" packer/preseed/Windows10/Autounattend.xml
|
||||
- |
|
||||
sed -i -e "s/<<img-password>>/$${WINRM_PASSWORD}/g" \
|
||||
packer/preseed/Windows10/Autounattend.xml \
|
||||
packer/preseed/Windows10/Sysprep_Unattend.xml
|
||||
sed -i -e "s/<<img-password>>/$${SSH_PASSWORD}/g" \
|
||||
packer/preseed/UbuntuServer20.04/user-data
|
||||
- |
|
||||
yamllint -d "{extends: relaxed, rules: {line-length: disable}}" scripts
|
||||
yamllint -d "{extends: relaxed, rules: {line-length: disable}}" \
|
||||
ansible \
|
||||
packer/preseed/UbuntuServer20.04/user-data \
|
||||
scripts
|
||||
- |
|
||||
packer init -upgrade \
|
||||
./packer
|
||||
- |
|
||||
packer validate \
|
||||
-var vm_name=$DRONE_BUILD_NUMBER-${DRONE_COMMIT_SHA:0:10} \
|
||||
-var vm_guestos=win10 \
|
||||
-var vm_guestos=ubuntuserver20.04 \
|
||||
-var repo_username=$${REPO_USERNAME} \
|
||||
-var repo_password=$${REPO_PASSWORD} \
|
||||
-var vsphere_password=$${VSPHERE_PASSWORD} \
|
||||
-var winrm_password=$${WINRM_PASSWORD} \
|
||||
-var ssh_password=$${SSH_PASSWORD} \
|
||||
./packer
|
||||
- |
|
||||
packer build \
|
||||
-on-error=cleanup \
|
||||
-on-error=cleanup -timestamp-ui \
|
||||
-var vm_name=$DRONE_BUILD_NUMBER-${DRONE_COMMIT_SHA:0:10} \
|
||||
-var vm_guestos=win10 \
|
||||
-var vm_guestos=ubuntuserver20.04 \
|
||||
-var repo_username=$${REPO_USERNAME} \
|
||||
-var repo_password=$${REPO_PASSWORD} \
|
||||
-var vsphere_password=$${VSPHERE_PASSWORD} \
|
||||
-var winrm_password=$${WINRM_PASSWORD} \
|
||||
-var ssh_password=$${SSH_PASSWORD} \
|
||||
./packer
|
||||
environment:
|
||||
VSPHERE_PASSWORD:
|
||||
from_secret: vsphere_password
|
||||
WINRM_PASSWORD:
|
||||
from_secret: winrm_password
|
||||
SSH_PASSWORD:
|
||||
from_secret: ssh_password
|
||||
REPO_USERNAME:
|
||||
from_secret: repo_username
|
||||
REPO_PASSWORD:
|
||||
from_secret: repo_password
|
||||
PRODUCTKEY:
|
||||
from_secret: prodkey_win10
|
||||
# PACKER_LOG: 1
|
||||
volumes:
|
||||
- name: output
|
||||
|
3
ansible/ansible.cfg
Normal file
3
ansible/ansible.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
[defaults]
|
||||
deprecation_warnings = False
|
||||
remote_tmp = /tmp/.ansible-${USER}/tmp
|
7
ansible/playbook.yml
Normal file
7
ansible/playbook.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
- hosts: all
|
||||
gather_facts: false
|
||||
become: true
|
||||
roles:
|
||||
- os
|
||||
- firstboot
|
10
ansible/roles/firstboot/files/ansible_payload/playbook.yml
Normal file
10
ansible/roles/firstboot/files/ansible_payload/playbook.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
- hosts: 127.0.0.1
|
||||
connection: local
|
||||
gather_facts: false
|
||||
# become: true
|
||||
roles:
|
||||
- vapp
|
||||
- network
|
||||
- users
|
||||
- cleanup
|
@ -0,0 +1,20 @@
|
||||
- name: Disable crontab job
|
||||
ansible.builtin.cron:
|
||||
name: firstboot
|
||||
state: absent
|
||||
- name: Restore extra tty
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/systemd/logind.conf
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
loop:
|
||||
- { regexp: '^NAutoVTs=', line: '#NAutoVTs=6'}
|
||||
- { regexp: '^ReserveVT=', line: '#ReserveVT=6'}
|
||||
- name: Unmask getty@tty1 service
|
||||
ansible.builtin.systemd:
|
||||
name: getty@tty1
|
||||
enabled: yes
|
||||
masked: no
|
||||
- name: Reboot host
|
||||
ansible.builtin.shell:
|
||||
cmd: /usr/sbin/reboot now
|
@ -0,0 +1,10 @@
|
||||
- name: Set hostname
|
||||
ansible.builtin.hostname:
|
||||
name: "{{ ovfproperties['guestinfo.hostname'] }}"
|
||||
- name: Create netplan configuration file
|
||||
ansible.builtin.template:
|
||||
src: netplan.j2
|
||||
dest: /etc/netplan/00-installer-config.yaml
|
||||
- name: Apply netplan configuration
|
||||
ansible.builtin.shell:
|
||||
cmd: /usr/sbin/netplan apply
|
@ -0,0 +1,10 @@
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
ens192:
|
||||
addresses:
|
||||
- {{ ovfproperties['guestinfo.ipaddress'] }}/{{ ovfproperties['guestinfo.prefixlength'] }}
|
||||
gateway4: {{ ovfproperties['guestinfo.gateway'] }}
|
||||
nameservers:
|
||||
addresses:
|
||||
- {{ ovfproperties['guestinfo.dnsserver'] }}
|
@ -0,0 +1,25 @@
|
||||
- name: Set root password
|
||||
ansible.builtin.user:
|
||||
name: root
|
||||
password: "{{ ovfproperties['guestinfo.rootpw'] | password_hash('sha512', 65534 | random(seed=ovfproperties['guestinfo.hostname']) | string) }}"
|
||||
generate_ssh_key: yes
|
||||
ssh_key_bits: 2048
|
||||
ssh_key_file: .ssh/id_rsa
|
||||
- name: Save root SSH publickey
|
||||
ansible.builtin.lineinfile:
|
||||
path: /root/.ssh/authorized_keys
|
||||
line: "{{ ovfproperties['guestinfo.rootsshkey'] }}"
|
||||
- name: Disable SSH password authentication
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regex: "{{ item.regex }}"
|
||||
line: "{{ item.line }}"
|
||||
state: "{{ item.state }}"
|
||||
loop:
|
||||
- { regex: '^#PasswordAuthentication', line: 'PasswordAuthentication no', state: present}
|
||||
- { regex: '^PasswordAuthentication yes', line: 'PasswordAuthentication yes', state: absent}
|
||||
- name: Delete 'ubuntu' user
|
||||
ansible.builtin.user:
|
||||
name: ubuntu
|
||||
state: absent
|
||||
remove: yes
|
@ -0,0 +1,21 @@
|
||||
- name: Store current ovfEnvironment
|
||||
ansible.builtin.shell:
|
||||
cmd: /usr/bin/vmtoolsd --cmd "info-get guestinfo.ovfEnv"
|
||||
register: ovfenv
|
||||
- name: Parse XML for vApp properties
|
||||
community.general.xml:
|
||||
xmlstring: "{{ ovfenv.stdout }}"
|
||||
namespaces:
|
||||
ns: http://schemas.dmtf.org/ovf/environment/1
|
||||
xpath: /ns:Environment/ns:PropertySection/ns:Property
|
||||
content: attribute
|
||||
register: ovfenv
|
||||
- name: Assign vApp properties to dictionary
|
||||
ansible.builtin.set_fact:
|
||||
ovfproperties: >-
|
||||
{{ ovfproperties | default({}) |
|
||||
combine({((item.values() | list)[0].values() | list)[0]:
|
||||
((item.values() | list)[0].values() | list)[1]})
|
||||
}}
|
||||
loop: "{{ ovfenv.matches }}"
|
||||
no_log: true
|
26
ansible/roles/firstboot/tasks/main.yml
Normal file
26
ansible/roles/firstboot/tasks/main.yml
Normal file
@ -0,0 +1,26 @@
|
||||
- name: Create destination folder
|
||||
ansible.builtin.file:
|
||||
path: /opt/firstboot
|
||||
state: directory
|
||||
- name: Create firstboot script file
|
||||
ansible.builtin.template:
|
||||
src: firstboot.j2
|
||||
dest: /opt/firstboot/firstboot.sh
|
||||
owner: root
|
||||
group: root
|
||||
mode: o+x
|
||||
- name: Create @reboot crontab job
|
||||
ansible.builtin.cron:
|
||||
name: firstboot
|
||||
special_time: reboot
|
||||
job: "/opt/firstboot/firstboot.sh"
|
||||
- name: Copy payload folder
|
||||
ansible.builtin.copy:
|
||||
src: ansible_payload/
|
||||
dest: /opt/firstboot/ansible/
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
- name: Install ansible-galaxy collection
|
||||
ansible.builtin.shell:
|
||||
cmd: ansible-galaxy collection install community.general
|
4
ansible/roles/firstboot/templates/firstboot.j2
Normal file
4
ansible/roles/firstboot/templates/firstboot.j2
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Apply firstboot configuration w/ ansible
|
||||
/usr/local/bin/ansible-playbook /opt/firstboot/ansible/playbook.yml | tee -a /var/log/firstboot.log > /dev/tty1
|
6
ansible/roles/os/tasks/ansible.yml
Normal file
6
ansible/roles/os/tasks/ansible.yml
Normal file
@ -0,0 +1,6 @@
|
||||
- name: Install ansible (w/ dependencies)
|
||||
ansible.builtin.pip:
|
||||
name: "{{ item }}"
|
||||
executable: pip3
|
||||
state: latest
|
||||
loop: "{{ pip_packages }}"
|
12
ansible/roles/os/tasks/cloud-init.yml
Normal file
12
ansible/roles/os/tasks/cloud-init.yml
Normal file
@ -0,0 +1,12 @@
|
||||
- name: Delete cloud-init package
|
||||
ansible.builtin.apt:
|
||||
name: cloud-init
|
||||
state: absent
|
||||
purge: yes
|
||||
- name: Delete cloud-init files
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- /etc/cloud
|
||||
- /var/lib/cloud
|
5
ansible/roles/os/tasks/logging.yml
Normal file
5
ansible/roles/os/tasks/logging.yml
Normal file
@ -0,0 +1,5 @@
|
||||
- name: Enable crontab logging
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/rsyslog.d/50-default.conf
|
||||
regexp: '^#cron\.\*.*'
|
||||
line: "cron.*\t\t\t\t./var/log/cron.log"
|
20
ansible/roles/os/tasks/main.yml
Normal file
20
ansible/roles/os/tasks/main.yml
Normal file
@ -0,0 +1,20 @@
|
||||
- name: Disable tty logins
|
||||
import_tasks: tty.yml
|
||||
|
||||
- name: Remove snapd
|
||||
import_tasks: snapd.yml
|
||||
|
||||
- name: Remove cloud-init
|
||||
import_tasks: cloud-init.yml
|
||||
|
||||
- name: Configure default logging
|
||||
import_tasks: logging.yml
|
||||
|
||||
- name: Configure services
|
||||
import_tasks: services.yml
|
||||
|
||||
- name: Install packages
|
||||
import_tasks: packages.yml
|
||||
|
||||
- name: Install ansible
|
||||
import_tasks: ansible.yml
|
15
ansible/roles/os/tasks/packages.yml
Normal file
15
ansible/roles/os/tasks/packages.yml
Normal file
@ -0,0 +1,15 @@
|
||||
- name: Install additional packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ item }}"
|
||||
state: latest
|
||||
update_cache: yes
|
||||
loop: "{{ packages }}"
|
||||
- name: Upgrade all packages
|
||||
ansible.builtin.apt:
|
||||
name: "*"
|
||||
state: latest
|
||||
update_cache: yes
|
||||
- name: Cleanup
|
||||
ansible.builtin.apt:
|
||||
autoremove: yes
|
||||
purge: yes
|
5
ansible/roles/os/tasks/services.yml
Normal file
5
ansible/roles/os/tasks/services.yml
Normal file
@ -0,0 +1,5 @@
|
||||
- name: Disable & mask networkd-wait-online
|
||||
ansible.builtin.systemd:
|
||||
name: systemd-networkd-wait-online
|
||||
enabled: no
|
||||
masked: yes
|
16
ansible/roles/os/tasks/snapd.yml
Normal file
16
ansible/roles/os/tasks/snapd.yml
Normal file
@ -0,0 +1,16 @@
|
||||
- name: Delete snapd package
|
||||
ansible.builtin.apt:
|
||||
name: snapd
|
||||
state: absent
|
||||
purge: yes
|
||||
- name: Delete leftover files
|
||||
ansible.builtin.file:
|
||||
path: /root/snap
|
||||
state: absent
|
||||
- name: Hold snapd package
|
||||
ansible.builtin.dpkg_selections:
|
||||
name: snapd
|
||||
selection: hold
|
||||
- name: Reload systemd unit configurations
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: yes
|
13
ansible/roles/os/tasks/tty.yml
Normal file
13
ansible/roles/os/tasks/tty.yml
Normal file
@ -0,0 +1,13 @@
|
||||
- name: Disable extra tty
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/systemd/logind.conf
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
loop:
|
||||
- { regexp: '^#NAutoVTs=', line: 'NAutoVTs=1'}
|
||||
- { regexp: '^#ReserveVT=', line: 'ReserveVT=11'}
|
||||
- name: Mask getty@tty1 service
|
||||
ansible.builtin.systemd:
|
||||
name: getty@tty1
|
||||
enabled: no
|
||||
masked: yes
|
11
ansible/roles/os/vars/main.yml
Normal file
11
ansible/roles/os/vars/main.yml
Normal file
@ -0,0 +1,11 @@
|
||||
packages:
|
||||
- jq
|
||||
# (python3-*) Dependency for installation of Ansible
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
- python3-wheel
|
||||
|
||||
pip_packages:
|
||||
- pip
|
||||
- ansible-core
|
||||
- lxml
|
@ -1,16 +0,0 @@
|
||||
script = <<-EOH
|
||||
$nic = get-netadapter
|
||||
|
||||
Get-NetAdapterBinding –InterfaceAlias $nic.name –ComponentID ms_tcpip6
|
||||
EOH
|
||||
|
||||
control "ipv6" do
|
||||
title 'Disabled network protocol IPv6'
|
||||
desc '
|
||||
This test assures that IPv6 is disabled
|
||||
'
|
||||
|
||||
describe powershell(script) do
|
||||
its('stdout') { should match 'False' }
|
||||
end
|
||||
end
|
@ -1,29 +0,0 @@
|
||||
script = <<-EOH
|
||||
# Initialize variable to empty array
|
||||
$NonCompliantServices = @()
|
||||
|
||||
# Specify relevant services
|
||||
$Services = @(
|
||||
"wuauserv",
|
||||
"W3SVC",
|
||||
"XboxGipSvc",
|
||||
"XblGameSave"
|
||||
)
|
||||
|
||||
# Enumerate all services
|
||||
$NonCompliantServices += Get-Service $Services -ErrorAction 'SilentlyContinue' | Where-Object {$_.StartType -ne 'Disabled'}
|
||||
|
||||
# Output; 'True' or list of noncompliant services
|
||||
Write-Output ($True, $NonCompliantServices)[!($NonCompliantServices.Count -eq 0)]
|
||||
EOH
|
||||
|
||||
control "disabled_services" do
|
||||
title 'Disabled services'
|
||||
desc '
|
||||
This test assures that all unneeded services are set to "disabled".
|
||||
'
|
||||
|
||||
describe powershell(script) do
|
||||
its('stdout') { should match 'True' }
|
||||
end
|
||||
end
|
@ -1,29 +0,0 @@
|
||||
script = <<-EOH
|
||||
# Initialize variable to empty array
|
||||
$LogicalDisks = @()
|
||||
|
||||
# Enumerate all logicaldisks
|
||||
# DriveType:
|
||||
# Unknown (0)
|
||||
# No Root Directory (1)
|
||||
# Removable Disk (2)
|
||||
# Local Disk (3)
|
||||
# Network Drive (4)
|
||||
# Compact Disc (5)
|
||||
# RAM Disk (6)
|
||||
$LogicalDisks += Get-WmiObject -Class 'win32_logicaldisk' -Filter 'DriveType=3'
|
||||
|
||||
# Filter/Quantify
|
||||
($LogicalDisks.Count -eq 1) -and (($LogicalDisks | Where-Object {$_.DeviceID -ne 'C:'}).Count -eq 0)
|
||||
EOH
|
||||
|
||||
control "single_disk" do
|
||||
title 'Single Disk'
|
||||
desc '
|
||||
This test assures that only a single disk (C:) is available
|
||||
'
|
||||
|
||||
describe powershell(script) do
|
||||
its('stdout') { should match 'True' }
|
||||
end
|
||||
end
|
@ -1,54 +0,0 @@
|
||||
control "software_installed-7zip" do
|
||||
title 'Included Default Applications: 7-Zip'
|
||||
desc '
|
||||
This test assures that the software application "7-Zip" is installed.
|
||||
'
|
||||
|
||||
describe chocolatey_package('7zip.install') do
|
||||
it { should be_installed }
|
||||
end
|
||||
end
|
||||
|
||||
# control "software_installed-dotnetfx" do
|
||||
# title 'Included Default Applications: .NET'
|
||||
# desc '
|
||||
# This test assures that the software application ".NET" is installed.
|
||||
# '
|
||||
|
||||
# describe chocolatey_package('dotnetfx') do
|
||||
# it { should be_installed }
|
||||
# end
|
||||
# end
|
||||
|
||||
# control "software_installed-foxitreader" do
|
||||
# title 'Included Default Applications: Foxit Reader'
|
||||
# desc '
|
||||
# This test assures that the software application "Foxit Reader" is installed.
|
||||
# '
|
||||
|
||||
# describe chocolatey_package('foxitreader') do
|
||||
# it { should be_installed }
|
||||
# end
|
||||
# end
|
||||
|
||||
# control "software_installed-notepadplusplus" do
|
||||
# title 'Included Default Applications: Notepad++'
|
||||
# desc '
|
||||
# This test assures that the software application "Notepad++" is installed.
|
||||
# '
|
||||
|
||||
# describe chocolatey_package('notepadplusplus') do
|
||||
# it { should be_installed }
|
||||
# end
|
||||
# end
|
||||
|
||||
# control "software_installed-putty" do
|
||||
# title 'Included Default Applications: Putty'
|
||||
# desc '
|
||||
# This test assures that the software application "PuTTy" is installed.
|
||||
# '
|
||||
|
||||
# describe chocolatey_package('putty') do
|
||||
# it { should be_installed }
|
||||
# end
|
||||
# end
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
name: Windows 10 IoT Enterprise
|
||||
title: Windows 10 IoT Enterprise InSpec Tests
|
||||
summary: Unit test for Windows 10 IoT Enterprise
|
||||
version: 1.0.0
|
||||
maintainer: https://code.spamasaurus.com/djpbessems
|
||||
copyright: https://code.spamasaurus.com/djpbessems
|
||||
license: Proprietary
|
||||
supports:
|
||||
- platform-family: windows
|
4
packer/iso.auto.pkrvars.hcl
Normal file
4
packer/iso.auto.pkrvars.hcl
Normal file
@ -0,0 +1,4 @@
|
||||
iso_url = "sn.itch.fyi/Repository/iso/Canonical/Ubuntu%20Server%2020.04/ubuntu-20.04.4-live-server-amd64.iso"
|
||||
iso_checksum = "sha256:28CCDB56450E643BAD03BB7BCF7507CE3D8D90E8BF09E38F6BD9AC298A98EAAD"
|
||||
// iso_url = "sn.itch.fyi/Repository/iso/Canonical/Ubuntu%20Server%2020.04/ubuntu-20.04.2-live-server-amd64.iso"
|
||||
// iso_checksum = "sha256:D1F2BF834BBE9BB43FAF16F9BE992A6F3935E65BE0EDECE1DEE2AA6EB1767423"
|
0
packer/preseed/UbuntuServer20.04/meta-data
Normal file
0
packer/preseed/UbuntuServer20.04/meta-data
Normal file
29
packer/preseed/UbuntuServer20.04/user-data
Normal file
29
packer/preseed/UbuntuServer20.04/user-data
Normal file
@ -0,0 +1,29 @@
|
||||
#cloud-config
|
||||
autoinstall:
|
||||
version: 1
|
||||
locale: en_US
|
||||
keyboard:
|
||||
layout: en
|
||||
variant: us
|
||||
network:
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
ens192:
|
||||
dhcp4: true
|
||||
dhcp-identifier: mac
|
||||
storage:
|
||||
layout:
|
||||
name: direct
|
||||
identity:
|
||||
hostname: packer-template
|
||||
username: ubuntu
|
||||
# password: $6$ZThRyfmSMh9499ar$KSZus58U/l58Efci0tiJEqDKFCpoy.rv25JjGRv5.iL33AQLTY2aljumkGiDAiX6LsjzVsGTgH85Tx4S.aTfx0
|
||||
password: $6$rounds=4096$ZKfzRoaQOtc$M.fhOsI0gbLnJcCONXz/YkPfSoefP4i2/PQgzi2xHEi2x9CUhush.3VmYKL0XVr5JhoYvnLfFwqwR/1YYEqZy/
|
||||
ssh:
|
||||
install-server: yes
|
||||
allow-pw: true
|
||||
user-data:
|
||||
disable_root: false
|
||||
late-commands:
|
||||
- echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu
|
@ -1,159 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<servicing/>
|
||||
<settings pass="windowsPE">
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<DiskConfiguration>
|
||||
<Disk wcm:action="add">
|
||||
<CreatePartitions>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Type>Primary</Type>
|
||||
<Extend>true</Extend>
|
||||
</CreatePartition>
|
||||
</CreatePartitions>
|
||||
<ModifyPartitions>
|
||||
<ModifyPartition wcm:action="add">
|
||||
<Extend>false</Extend>
|
||||
<Format>NTFS</Format>
|
||||
<Letter>C</Letter>
|
||||
<Order>1</Order>
|
||||
<PartitionID>1</PartitionID>
|
||||
<Label>Windows 10</Label>
|
||||
</ModifyPartition>
|
||||
</ModifyPartitions>
|
||||
<DiskID>0</DiskID>
|
||||
<WillWipeDisk>true</WillWipeDisk>
|
||||
</Disk>
|
||||
<WillShowUI>OnError</WillShowUI>
|
||||
</DiskConfiguration>
|
||||
<UserData>
|
||||
<AcceptEula>true</AcceptEula>
|
||||
<!-- <FullName>Spamasaurus Rex</FullName>
|
||||
<Organization>Spamasaurus Rex</Organization> -->
|
||||
<ProductKey>
|
||||
<Key><<img-productkey>></Key>
|
||||
<WillShowUI>Never</WillShowUI>
|
||||
</ProductKey>
|
||||
</UserData>
|
||||
<ImageInstall>
|
||||
<OSImage>
|
||||
<InstallTo>
|
||||
<DiskID>0</DiskID>
|
||||
<PartitionID>1</PartitionID>
|
||||
</InstallTo>
|
||||
<WillShowUI>OnError</WillShowUI>
|
||||
<InstallToAvailablePartition>false</InstallToAvailablePartition>
|
||||
<InstallFrom>
|
||||
<MetaData wcm:action="add">
|
||||
<Key>/IMAGE/INDEX</Key>
|
||||
<Value>3</Value>
|
||||
</MetaData>
|
||||
</InstallFrom>
|
||||
</OSImage>
|
||||
</ImageInstall>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<SetupUILanguage>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
</SetupUILanguage>
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UILanguageFallback>en-US</UILanguageFallback>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="offlineServicing">
|
||||
<component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<EnableLUA>false</EnableLUA>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value><<img-password>></Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<NetworkLocation>Home</NetworkLocation>
|
||||
<ProtectYourPC>1</ProtectYourPC>
|
||||
</OOBE>
|
||||
<AutoLogon>
|
||||
<Password>
|
||||
<Value><<img-password>></Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
<Username>administrator</Username>
|
||||
<Enabled>true</Enabled>
|
||||
</AutoLogon>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine>
|
||||
<Description>Set execution policy 64bit</Description>
|
||||
<Order>1</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine>
|
||||
<Description>Set execution policy 32bit</Description>
|
||||
<Order>2</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c reg add "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff"</CommandLine>
|
||||
<Description>Disable new network prompt</Description>
|
||||
<Order>3</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\Set-NetworkProfile.ps1</CommandLine>
|
||||
<Description>Set network profile to private</Description>
|
||||
<Order>4</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\Disable-WinRM.ps1</CommandLine>
|
||||
<Description>Disable WinRM</Description>
|
||||
<Order>5</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c a:\Install-VMwareTools.cmd</CommandLine>
|
||||
<Order>13</Order>
|
||||
<Description>Install VMware Tools</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\Enable-WinRM.ps1</CommandLine>
|
||||
<Description>Enable WinRM</Description>
|
||||
<Order>99</Order>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
<ShowWindowsLive>false</ShowWindowsLive>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<OEMInformation>
|
||||
<HelpCustomized>false</HelpCustomized>
|
||||
</OEMInformation>
|
||||
<!-- Rename computer here. -->
|
||||
<ComputerName>packer-template</ComputerName>
|
||||
<TimeZone>W. Europe Standard Time</TimeZone>
|
||||
<RegisteredOwner/>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<SkipAutoActivation>true</SkipAutoActivation>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<settings pass="generalize">
|
||||
<component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<SkipRearm>1</SkipRearm>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
|
||||
<DoNotCleanUpNonPresentDevices>true</DoNotCleanUpNonPresentDevices>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<HideLocalAccountScreen>true</HideLocalAccountScreen>
|
||||
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<NetworkLocation>Work</NetworkLocation>
|
||||
<ProtectYourPC>1</ProtectYourPC>
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
</OOBE>
|
||||
<TimeZone>UTC</TimeZone>
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value><<img-password>></Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
</settings>
|
||||
</unattend>
|
100
packer/ubuntuserver20.04.pkr.hcl
Normal file
100
packer/ubuntuserver20.04.pkr.hcl
Normal file
@ -0,0 +1,100 @@
|
||||
packer {
|
||||
required_plugins {
|
||||
}
|
||||
}
|
||||
|
||||
source "vsphere-iso" "ubuntuserver" {
|
||||
vcenter_server = var.vcenter_server
|
||||
username = var.vsphere_username
|
||||
password = var.vsphere_password
|
||||
insecure_connection = "true"
|
||||
|
||||
vm_name = "${var.vm_guestos}-${var.vm_name}"
|
||||
datacenter = var.vsphere_datacenter
|
||||
cluster = var.vsphere_cluster
|
||||
host = var.vsphere_host
|
||||
folder = var.vsphere_folder
|
||||
datastore = var.vsphere_datastore
|
||||
|
||||
guest_os_type = "ubuntu64Guest"
|
||||
|
||||
boot_order = "disk,cdrom"
|
||||
boot_command = [
|
||||
"<enter><wait2><enter><wait><f6><esc><wait>",
|
||||
" autoinstall<wait2> ds=nocloud;",
|
||||
"<wait><enter>"
|
||||
]
|
||||
boot_wait = "2s"
|
||||
|
||||
communicator = "ssh"
|
||||
ssh_username = "ubuntu"
|
||||
ssh_password = var.ssh_password
|
||||
ssh_timeout = "20m"
|
||||
ssh_handshake_attempts = "100"
|
||||
ssh_pty = true
|
||||
|
||||
CPUs = 2
|
||||
RAM = 4096
|
||||
|
||||
network_adapters {
|
||||
network = var.vsphere_network
|
||||
network_card = "vmxnet3"
|
||||
}
|
||||
storage {
|
||||
disk_size = 20480
|
||||
disk_thin_provisioned = true
|
||||
}
|
||||
disk_controller_type = ["pvscsi"]
|
||||
usb_controller = ["xhci"]
|
||||
|
||||
cd_files = [
|
||||
"packer/preseed/UbuntuServer20.04/user-data",
|
||||
"packer/preseed/UbuntuServer20.04/meta-data"
|
||||
]
|
||||
cd_label = "cidata"
|
||||
iso_url = local.iso_authenticatedurl
|
||||
iso_checksum = var.iso_checksum
|
||||
|
||||
shutdown_command = "echo '${var.ssh_password}' | sudo -S shutdown -P now"
|
||||
shutdown_timeout = "5m"
|
||||
|
||||
export {
|
||||
images = false
|
||||
output_directory = "/scratch/ubuntuserver"
|
||||
}
|
||||
remove_cdrom = true
|
||||
}
|
||||
|
||||
build {
|
||||
sources = [
|
||||
"source.vsphere-iso.ubuntuserver"
|
||||
]
|
||||
|
||||
provisioner "ansible" {
|
||||
only = ["vsphere-iso.ubuntuserver"]
|
||||
|
||||
playbook_file = "ansible/playbook.yml"
|
||||
user = "ubuntu"
|
||||
ansible_env_vars = [
|
||||
"ANSIBLE_CONFIG=ansible/ansible.cfg"
|
||||
]
|
||||
use_proxy = "false"
|
||||
extra_arguments = [
|
||||
"--extra-vars", "ansible_ssh_pass=${var.ssh_password}"
|
||||
]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
only = ["vsphere-iso.ubuntuserver"]
|
||||
inline = [
|
||||
"pwsh -command \"& scripts/Update-OvfConfiguration.ps1 \\",
|
||||
" -OVFFile '/scratch/ubuntuserver/${var.vm_guestos}-${var.vm_name}.ovf' \\",
|
||||
" -Parameter @{'appliance.name'='${var.vm_guestos}';'appliance.version'='${var.vm_name}'}\"",
|
||||
"pwsh -file scripts/Update-Manifest.ps1 \\",
|
||||
" -ManifestFileName '/scratch/ubuntuserver/${var.vm_guestos}-${var.vm_name}.mf'",
|
||||
"ovftool --acceptAllEulas --allowExtraConfig --overwrite \\",
|
||||
" '/scratch/ubuntuserver/${var.vm_guestos}-${var.vm_name}.ovf' \\",
|
||||
" /output/Ubuntu-Server-20.04.ova"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
variable "vcenter_server" {}
|
||||
variable "vsphere_username" {}
|
||||
variable "vsphere_password" {}
|
||||
variable "vsphere_password" {
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "vsphere_host" {}
|
||||
variable "vsphere_datacenter" {}
|
||||
variable "vsphere_cluster" {}
|
||||
|
||||
variable "vsphere_templatefolder" {}
|
||||
variable "vsphere_folder" {}
|
||||
@ -12,7 +15,17 @@ variable "vsphere_network" {}
|
||||
|
||||
variable "vm_name" {}
|
||||
variable "vm_guestos" {}
|
||||
variable "winrm_password" {}
|
||||
variable "ssh_password" {
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "iso_url" {}
|
||||
variable "iso_checksum" {}
|
||||
variable "repo_username" {}
|
||||
variable "repo_password" {}
|
||||
variable "repo_password" {
|
||||
sensitive = true
|
||||
}
|
||||
local "iso_authenticatedurl" {
|
||||
expression = "https://${var.repo_username}:${var.repo_password}@${var.iso_url}"
|
||||
sensitive = true
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
vcenter_server = "bv11-vc.bessems.lan"
|
||||
vsphere_username = "administrator@vsphere.local"
|
||||
vsphere_datacenter = "DeSchakel"
|
||||
vsphere_cluster = "Cluster.Legacy"
|
||||
vsphere_host = "bv11-esx.bessems.lan"
|
||||
vsphere_datastore = "Datastore01.SSD"
|
||||
vsphere_datastore = "ESX00.SSD01"
|
||||
vsphere_folder = "/Packer"
|
||||
vsphere_templatefolder = "/Templates"
|
||||
vsphere_network = "LAN"
|
@ -1,133 +0,0 @@
|
||||
packer {
|
||||
required_plugins {
|
||||
windows-update = {
|
||||
version = ">= 0.12.0"
|
||||
source = "github.com/rgl/windows-update"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source "vsphere-iso" "win10" {
|
||||
vcenter_server = var.vcenter_server
|
||||
username = var.vsphere_username
|
||||
password = var.vsphere_password
|
||||
insecure_connection = "true"
|
||||
|
||||
vm_name = "${var.vm_guestos}-${var.vm_name}"
|
||||
datacenter = var.vsphere_datacenter
|
||||
host = var.vsphere_host
|
||||
folder = var.vsphere_folder
|
||||
datastore = var.vsphere_datastore
|
||||
|
||||
guest_os_type = "windows9_64Guest"
|
||||
|
||||
boot_order = "disk,cdrom"
|
||||
boot_command = [""]
|
||||
boot_wait = "5m"
|
||||
|
||||
communicator = "winrm"
|
||||
winrm_username = "administrator"
|
||||
winrm_password = var.winrm_password
|
||||
winrm_timeout = "10m"
|
||||
|
||||
CPUs = 2
|
||||
RAM = 8192
|
||||
|
||||
network_adapters {
|
||||
network = var.vsphere_network
|
||||
network_card = "vmxnet3"
|
||||
}
|
||||
storage {
|
||||
disk_size = 20480
|
||||
disk_thin_provisioned = true
|
||||
}
|
||||
disk_controller_type = ["lsilogic-sas"]
|
||||
usb_controller = ["xhci"]
|
||||
|
||||
floppy_files = [
|
||||
"packer/preseed/Windows10/Autounattend.xml",
|
||||
"packer/preseed/Windows10/Sysprep_Unattend.xml",
|
||||
"scripts/Set-NetworkProfile.ps1",
|
||||
"scripts/Disable-WinRM.ps1",
|
||||
"scripts/Enable-WinRM.ps1",
|
||||
"scripts/Install-VMwareTools.cmd"
|
||||
]
|
||||
iso_checksum = "sha256:8D1663B71280533824CF95C7AB48ADAF5A187C38FCFF5B16A569F903688916D0"
|
||||
iso_paths = [
|
||||
"ISO-files/VMware-tools-windows-11.2.1-17243207/VMware-tools-windows-11.2.1-17243207.iso"
|
||||
]
|
||||
iso_url = "https://${var.repo_username}:${var.repo_password}@sn.itch.fyi/Repository/iso/Microsoft/Windows%2010/20H2/en_windows_10_enterprise_20H2_x64.iso"
|
||||
|
||||
shutdown_command = "C:\\Windows\\System32\\Sysprep\\sysprep.exe /generalize /oobe /unattend:A:\\Sysprep_Unattend.xml"
|
||||
shutdown_timeout = "1h"
|
||||
|
||||
export {
|
||||
images = false
|
||||
output_directory = "/scratch/win10"
|
||||
}
|
||||
remove_cdrom = true
|
||||
}
|
||||
|
||||
build {
|
||||
sources = ["source.vsphere-iso.win10"]
|
||||
|
||||
provisioner "windows-update" {
|
||||
filters = [
|
||||
"exclude:$_.Title -like '*Preview*'",
|
||||
"include:$true"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "powershell" {
|
||||
inline = [
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12",
|
||||
"Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "powershell" {
|
||||
inline = [
|
||||
"choco config set --name=limit-output --value=LimitOutput",
|
||||
"choco install -y 7zip.install",
|
||||
"choco install -y sysinternals",
|
||||
"choco install -y firefox"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "windows-update" {
|
||||
filters = [
|
||||
"exclude:$_.Title -like '*Preview*'",
|
||||
"include:$true"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "powershell" {
|
||||
inline = [
|
||||
"New-Item -Path 'C:\\Payload\\Scripts' -ItemType 'Directory' -Force:$True -Confirm:$False"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
destination = "C:\\Payload\\"
|
||||
source = "scripts/Windows10/payload/"
|
||||
}
|
||||
|
||||
provisioner "powershell" {
|
||||
scripts = [
|
||||
"scripts/Windows10/Register-ScheduledTask.ps1"
|
||||
]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = [
|
||||
"pwsh -command \"& scripts/Update-OvfConfiguration.ps1 \\",
|
||||
" -OVFFile '/scratch/win10/${var.vm_guestos}-${var.vm_name}.ovf' \\",
|
||||
" -Parameter @{'appliance.name'='${var.vm_guestos}';'appliance.version'='${var.vm_name}'}\"",
|
||||
"pwsh -file scripts/Update-Manifest.ps1 \\",
|
||||
" -ManifestFileName '/scratch/win10/${var.vm_guestos}-${var.vm_name}.mf'",
|
||||
"ovftool --acceptAllEulas --allowExtraConfig --overwrite \\",
|
||||
" '/scratch/win10/${var.vm_guestos}-${var.vm_name}.ovf' \\",
|
||||
" /output/Windows10.ova"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
|
||||
netsh advfirewall firewall set rule group="Windows Remote Management" new enable=yes
|
||||
$winrmService = Get-Service -Name WinRM
|
||||
if ($winrmService.Status -eq "Running"){
|
||||
Disable-PSRemoting -Force
|
||||
}
|
||||
Stop-Service winrm
|
||||
Set-Service -Name winrm -StartupType Disabled
|
@ -1,18 +0,0 @@
|
||||
$NetworkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
|
||||
$Connections = $NetworkListManager.GetNetworkConnections()
|
||||
$Connections | ForEach-Object { $_.GetNetwork().SetCategory(1) }
|
||||
|
||||
Enable-PSRemoting -Force
|
||||
winrm quickconfig -q
|
||||
winrm quickconfig -transport:http
|
||||
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
|
||||
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="800"}'
|
||||
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
|
||||
winrm set winrm/config/service/auth '@{Basic="true"}'
|
||||
winrm set winrm/config/client/auth '@{Basic="true"}'
|
||||
winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}'
|
||||
netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow
|
||||
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" profile=public new remoteip=any
|
||||
Set-Service winrm -startuptype "auto"
|
||||
Restart-Service winrm
|
@ -1,2 +0,0 @@
|
||||
@rem Silent mode, basic UI, no reboot
|
||||
e:\setup64 /s /v "/qb REBOOT=R"
|
@ -1,73 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<BlockList>
|
||||
<!-- services to disable -->
|
||||
<Services>
|
||||
<Name>MVMCP2VAgent</Name>
|
||||
<Name>VMTools</Name>
|
||||
<Name> VMUpgradeHelper </Name>
|
||||
<Name> vmvss </Name>
|
||||
<Name>vmdesched</Name>
|
||||
<Name>Virtual Server</Name>
|
||||
<!-- Virtual Machine Helper -->
|
||||
<Name>vmh</Name>
|
||||
<!-- Xen-specific service -->
|
||||
<Name>xensvc</Name>
|
||||
</Services>
|
||||
<!-- drivers to disable -->
|
||||
<Drivers>
|
||||
<Name>vmx_svga</Name>
|
||||
<Name>vmmouse</Name>
|
||||
<Name>vmscsi</Name>
|
||||
<Name>amdpcn</Name>
|
||||
<Name>PCnet</Name>
|
||||
<Name>VMMEMCTL</Name>
|
||||
|
||||
<Name> pvscsi </Name>
|
||||
<Name> vmci </Name>
|
||||
<Name> vmmouse </Name>
|
||||
<Name> vmaudio </Name>
|
||||
<Name> vmrawdsk </Name>
|
||||
<Name> vmxnet </Name>
|
||||
<Name> vmxnet3ndis6 </Name>
|
||||
<Name> vm3dmp </Name>
|
||||
<Name> vmdebug </Name>
|
||||
<Name> vmxnet3ndis5 </Name>
|
||||
|
||||
|
||||
<Name>cirrus</Name>
|
||||
<!-- storage drivers -->
|
||||
<Name>buslogic</Name>
|
||||
<Name>symc810</Name>
|
||||
<Name>cpqarray</Name>
|
||||
<Name>pcntn4m</Name>
|
||||
<Name>cpqnf3</Name>
|
||||
<Name>MRaidNT</Name>
|
||||
<Name>Symc8XX</Name>
|
||||
<!-- VIA chipset drivers -->
|
||||
<Name>viaide</Name>
|
||||
<Name>VIAudio</Name>
|
||||
<Name>VIAPFD</Name>
|
||||
<Name>viafilter</Name>
|
||||
<Name>viaagp</Name>
|
||||
<Name>viaagp1</Name>
|
||||
<!-- network drivers: Intel(R) PRO/100 -->
|
||||
<Name>E100B</Name>
|
||||
<!-- tape drivers -->
|
||||
<Name>4mmdat</Name>
|
||||
<Name>4mmdat-SeSFT</Name>
|
||||
<Name>SCSIChanger</Name>
|
||||
|
||||
<!-- Virtual Machine Monitor -->
|
||||
<Name>vmm</Name>
|
||||
<!-- Xen-specific drivers -->
|
||||
<Name>xenevtchn</Name>
|
||||
<Name>xenvbd</Name>
|
||||
<Name>xennet</Name>
|
||||
</Drivers>
|
||||
<Programs>
|
||||
<Name>ProMON</Name>
|
||||
<Name>s3tray2</Name>
|
||||
<Name>VMwareTray</Name>
|
||||
<Name>VMwareUser</Name>
|
||||
</Programs>
|
||||
</BlockList>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,23 +0,0 @@
|
||||
# You cannot enable Windows PowerShell Remoting on network connections that are set to Public
|
||||
# Spin through all the network locations and if they are set to Public, set them to Private
|
||||
# using the INetwork interface:
|
||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa370750(v=vs.85).aspx
|
||||
# For more info, see:
|
||||
# http://blogs.msdn.com/b/powershell/archive/2009/04/03/setting-network-location-to-private.aspx
|
||||
|
||||
# Network location feature was only introduced in Windows Vista - no need to bother with this
|
||||
# if the operating system is older than Vista
|
||||
if([environment]::OSVersion.version.Major -lt 6) { return }
|
||||
|
||||
# You cannot change the network location if you are joined to a domain, so abort
|
||||
if(1,3,4,5 -contains (Get-WmiObject win32_computersystem).DomainRole) { return }
|
||||
|
||||
# Get network connections
|
||||
$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
|
||||
$connections = $networkListManager.GetNetworkConnections()
|
||||
|
||||
$connections |foreach {
|
||||
Write-Host $_.GetNetwork().GetName()"category was previously set to"$_.GetNetwork().GetCategory()
|
||||
$_.GetNetwork().SetCategory(1)
|
||||
Write-Host $_.GetNetwork().GetName()"changed to category"$_.GetNetwork().GetCategory()
|
||||
}
|
@ -47,7 +47,77 @@ $GetContentSplat = @{
|
||||
}
|
||||
$XML = [xml](Get-Content @GetContentSplat)
|
||||
$NS = [System.Xml.XmlNamespaceManager]$XML.NameTable
|
||||
[void]$NS.AddNamespace('Any', $XML.DocumentElement.xmlns)
|
||||
[void]$NS.AddNamespace('ns', $XML.DocumentElement.xmlns)
|
||||
[void]$NS.AddNamespace('ovf', $XML.DocumentElement.ovf)
|
||||
[void]$NS.AddNamespace('rasd', $XML.DocumentElement.rasd)
|
||||
[void]$NS.AddNamespace('vmw', $XML.DocumentElement.vmw)
|
||||
|
||||
# Create copy of existing 'Item/ResourceType'=17 (=Hard disk) node
|
||||
$XMLDiskTemplate = $XML.SelectSingleNode("//ns:VirtualHardwareSection/ns:Item/rasd:ResourceType[.='17']", $NS).ParentNode.CloneNode($True)
|
||||
|
||||
ForEach ($Disk in $OVFConfig.DynamicDisks) {
|
||||
# Determine next free available 'diskId'
|
||||
$XMLDisks = $XML.SelectNodes("//ns:DiskSection/ns:Disk[contains(@ovf:diskId,'vmdisk')]", $NS)
|
||||
$DiskId = 1
|
||||
While ($XMLDisks.DiskId -contains "vmdisk$($DiskId)") {
|
||||
$DiskId++
|
||||
}
|
||||
|
||||
# Add new 'Disk' node (under 'DiskSection')
|
||||
$XMLDisk = $XML.CreateElement('Disk', $XML.DocumentElement.xmlns)
|
||||
$PowersMap = @{
|
||||
KB = 10
|
||||
MB = 20
|
||||
GB = 30
|
||||
TB = 40
|
||||
PB = 50
|
||||
}
|
||||
If ($PowersMap.Keys -notcontains $Disk.UnitSize) {
|
||||
# Invalid UnitSize; skipping adding new disk
|
||||
Continue
|
||||
}
|
||||
|
||||
[void]$XMLDisk.SetAttribute('capacityAllocationUnits', $NS.LookupNamespace('ovf'), "byte * 2^$($PowersMap[$Disk.UnitSize])")
|
||||
[void]$XMLDisk.SetAttribute('format', $NS.LookupNamespace('ovf'), 'http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized')
|
||||
[void]$XMLDisk.SetAttribute('diskId', $NS.LookupNamespace('ovf'), "vmdisk$($DiskId)")
|
||||
[void]$XMLDisk.SetAttribute('capacity', $NS.LookupNamespace('ovf'), '${{vmconfig.disksize.{0}}}' -f $DiskId)
|
||||
[void]$XMLDisk.SetAttribute('populatedSize', $NS.LookupNamespace('ovf'), 0)
|
||||
[void]$XML.SelectSingleNode('//ns:DiskSection', $NS).AppendChild($XMLDisk)
|
||||
|
||||
# Add new 'Item/ResourceType' node (under 'VirtualHardwareSection')
|
||||
$XMLDiskItem = $XMLDiskTemplate.CloneNode($True)
|
||||
$XMLDiskItem.SelectSingleNode('rasd:AddressOnParent', $NS).InnerText = ($DiskId - 1)
|
||||
$XMLDiskItem.SelectSingleNode('rasd:ElementName', $NS).InnerText = "Hard Disk $($DiskId)"
|
||||
$XMLDiskItem.SelectSingleNode('rasd:HostResource', $NS).InnerText = "ovf:/disk/vmdisk$($DiskId)"
|
||||
# Determine next free available and highest 'InstanceID'
|
||||
$InstanceIDs = $XML.SelectNodes('//ns:VirtualHardwareSection/ns:Item/rasd:InstanceID', $NS).InnerText
|
||||
$InstanceID = 1
|
||||
While ($InstanceIDs -contains $InstanceID) {
|
||||
$InstanceID++
|
||||
}
|
||||
$HighestInstanceID = ($InstanceIDs | Measure-Object -Maximum).Maximum
|
||||
$XMLDiskItem.SelectSingleNode('rasd:InstanceID', $NS).InnerText = $InstanceID
|
||||
[void]$XML.SelectSingleNode('//ns:VirtualHardwareSection', $NS).InsertAfter(
|
||||
$XMLDiskItem,
|
||||
$XML.SelectSingleNode("//ns:VirtualHardwareSection/ns:Item/rasd:InstanceID[.='$($HighestInstanceID)']", $NS).ParentNode
|
||||
)
|
||||
|
||||
$OVFConfig.PropertyCategories[0].ProductProperties += @{
|
||||
Key = "vmconfig.disksize.$($DiskId)"
|
||||
Type = If ([boolean]$Disk.Constraints.Minimum -or [boolean]$Disk.Constraints.Maximum) {
|
||||
"Int($($Disk.Constraints.Minimum)..$($Disk.Constraints.Maximum))"
|
||||
}
|
||||
Else {
|
||||
'Int'
|
||||
}
|
||||
Label = "Disk $($DiskId) size*"
|
||||
Description = "$($Disk.Description) (in $($Disk.UnitSize))".Trim()
|
||||
DefaultValue = "$($Disk.Constraints.Minimum)"
|
||||
Configurations = '*'
|
||||
UserConfigurable = 'true'
|
||||
}
|
||||
}
|
||||
Write-Host "Inserted $($OVFConfig.DynamicDisks.Count) new node(s) into 'DiskSection' and 'VirtualHardwareSection' respectively"
|
||||
|
||||
If ($OVFConfig.DeploymentConfigurations.Count -gt 0) {
|
||||
$XMLSection = $XML.CreateElement('DeploymentOptionSection', $XML.DocumentElement.xmlns)
|
||||
@ -58,52 +128,72 @@ If ($OVFConfig.DeploymentConfigurations.Count -gt 0) {
|
||||
ForEach ($Configuration in $OVFConfig.DeploymentConfigurations) {
|
||||
$XMLConfig = $XML.CreateElement('Configuration', $XML.DocumentElement.xmlns)
|
||||
|
||||
$XMLConfigAttrId = $XML.CreateAttribute('id', $XML.DocumentElement.ovf)
|
||||
$XMLConfigAttrId.Value = $Configuration.Id
|
||||
[void]$XMLConfig.SetAttribute('id', $NS.LookupNamespace('ovf'), $Configuration.Id)
|
||||
|
||||
$XMLConfigLabel = $XML.CreateElement('Label', $XML.DocumentElement.xmlns)
|
||||
$XMLConfigLabel.InnerText = $Configuration.Label
|
||||
|
||||
$XMLConfigDescription = $XML.CreateElement('Description', $XML.DocumentElement.xmlns)
|
||||
$XMLConfigDescription.InnerText = $Configuration.Description
|
||||
|
||||
[void]$XMLConfig.Attributes.Append($XMLConfigAttrId)
|
||||
[void]$XMLConfig.AppendChild($XMLConfigLabel)
|
||||
[void]$XMLConfig.AppendChild($XMLConfigDescription)
|
||||
|
||||
[void]$XMLSection.AppendChild($XMLConfig)
|
||||
}
|
||||
[void]$XML.SelectSingleNode('//Any:Envelope', $NS).InsertAfter($XMLSection, $XML.SelectSingleNode('//Any:NetworkSection', $NS))
|
||||
[void]$XML.SelectSingleNode('//ns:Envelope', $NS).InsertAfter($XMLSection, $XML.SelectSingleNode('//ns:NetworkSection', $NS))
|
||||
Write-Host "Inserted 'DeploymentOptionSection' with $($Configuration.Count) nodes"
|
||||
|
||||
If ($OVFConfig.DeploymentConfigurations.Count -eq $OVFConfig.DeploymentConfigurations.Size.Count) {
|
||||
# Create copies of existing 'Item/ResourceType' nodes
|
||||
$XMLCPUTemplate = $XML.SelectSingleNode("//ns:VirtualHardwareSection/ns:Item/rasd:ResourceType[.='3']", $NS).ParentNode.CloneNode($True)
|
||||
$XMLMemoryTemplate = $XML.SelectSingleNode("//ns:VirtualHardwareSection/ns:Item/rasd:ResourceType[.='4']", $NS).ParentNode.CloneNode($True)
|
||||
# Delete existing nodes
|
||||
ForEach ($Node in $XML.SelectNodes("//ns:VirtualHardwareSection/ns:Item/rasd:ResourceType[.='3' or .='4']", $NS).ParentNode) {
|
||||
[void]$Node.ParentNode.RemoveChild($Node)
|
||||
}
|
||||
# Add adjusted 'Item/ResourceType' nodes
|
||||
ForEach ($Configuration in $OVFConfig.DeploymentConfigurations) {
|
||||
$XMLCPU = $XMLCPUTemplate.CloneNode($True)
|
||||
[void]$XMLCPU.SetAttribute('configuration', $NS.LookupNamespace('ovf'), $Configuration.Id)
|
||||
$XMLCPU.SelectSingleNode('rasd:ElementName', $NS).InnerText = '{0} virtual CPU(s)' -f $Configuration.Size.CPU
|
||||
$XMLCPU.SelectSingleNode('rasd:VirtualQuantity', $NS).InnerText = $Configuration.Size.CPU
|
||||
|
||||
$XMLMemory = $XMLMemoryTemplate.CloneNode($True)
|
||||
[void]$XMLMemory.SetAttribute('configuration', $NS.LookupNamespace('ovf'), $Configuration.Id)
|
||||
$XMLMemory.SelectSingleNode('rasd:ElementName', $NS).InnerText = '{0}MB of memory' -f $Configuration.Size.Memory
|
||||
$XMLMemory.SelectSingleNode('rasd:VirtualQuantity', $NS).InnerText = $Configuration.Size.Memory
|
||||
|
||||
[void]$XML.SelectSingleNode('//ns:VirtualHardwareSection', $NS).InsertAfter(
|
||||
$XMLCPU,
|
||||
$XML.SelectSingleNode('//ns:VirtualHardwareSection/ns:System', $NS)
|
||||
)
|
||||
[void]$XML.SelectSingleNode('//ns:VirtualHardwareSection', $NS).InsertAfter(
|
||||
$XMLMemory,
|
||||
$XML.SelectSingleNode('//ns:VirtualHardwareSection/ns:System', $NS)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$XMLAttrTransport = $XML.CreateAttribute('transport', $XML.DocumentElement.ovf)
|
||||
$XMLAttrTransport.Value = 'com.vmware.guestInfo'
|
||||
[void]$XML.SelectSingleNode('//Any:VirtualHardwareSection', $NS).Attributes.Append($XMLAttrTransport)
|
||||
[void]$XML.SelectSingleNode('//ns:VirtualHardwareSection', $NS).SetAttribute('transport', $NS.LookupNamespace('ovf'), 'com.vmware.guestInfo')
|
||||
ForEach ($ExtraConfig in $OVFConfig.AdvancedOptions) {
|
||||
$XMLExtraConfig = $XML.CreateElement('vmw:ExtraConfig', $XML.DocumentElement.vmw)
|
||||
|
||||
$XMLExtraConfigAttrRequired = $XML.CreateAttribute('required', $XML.DocumentElement.ovf)
|
||||
$XMLExtraConfigAttrRequired.Value = "$([boolean]$ExtraConfig.Required)".ToLower()
|
||||
$XMLExtraConfigAttrKey = $XML.CreateAttribute('key', $XML.DocumentElement.vmw)
|
||||
$XMLExtraConfigAttrKey.Value = $ExtraConfig.Key
|
||||
$XMLExtraConfigAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.vmw)
|
||||
$XMLExtraConfigAttrValue.Value = $ExtraConfig.Value
|
||||
[void]$XMLExtraConfig.SetAttribute('required', $NS.LookupNamespace('ovf'), "$([boolean]$ExtraConfig.Required)".ToLower())
|
||||
[void]$XMLExtraConfig.SetAttribute('key', $NS.LookupNamespace('vmw'), $ExtraConfig.Key)
|
||||
[void]$XMLExtraConfig.SetAttribute('value', $NS.LookupNamespace('vmw'), $ExtraConfig.Value)
|
||||
|
||||
[void]$XMLExtraConfig.Attributes.Append($XMLExtraConfigAttrRequired)
|
||||
[void]$XMLExtraConfig.Attributes.Append($XMLExtraConfigAttrKey)
|
||||
[void]$XMLExtraConfig.Attributes.Append($XMLExtraConfigAttrValue)
|
||||
[void]$XML.SelectSingleNode('//Any:VirtualHardwareSection', $NS).AppendChild($XMLExtraConfig)
|
||||
[void]$XML.SelectSingleNode('//ns:VirtualHardwareSection', $NS).AppendChild($XMLExtraConfig)
|
||||
}
|
||||
Write-Host "Added $($OVFConfig.AdvancedOptions.Count) 'vmw:ExtraConfig' nodes"
|
||||
Write-Host "Added $($OVFConfig.AdvancedOptions.Count) 'vmw:ExtraConfig' node(s)"
|
||||
|
||||
$XMLProductSection = $XML.SelectSingleNode('//Any:ProductSection', $NS)
|
||||
$XMLProductSection = $XML.SelectSingleNode('//ns:ProductSection', $NS)
|
||||
If ($XMLProductSection -eq $Null) {
|
||||
$XMLProductSection = $XML.CreateElement('ProductSection', $XML.DocumentElement.xmlns)
|
||||
[void]$XML.SelectSingleNode('//Any:VirtualSystem', $NS).AppendChild($XMLProductSection)
|
||||
[void]$XML.SelectSingleNode('//ns:VirtualSystem', $NS).AppendChild($XMLProductSection)
|
||||
Write-Host "Inserted 'ProductSection'"
|
||||
} Else {
|
||||
ForEach ($Child in $XMLProductSection.SelectNodes('//Any:ProductSection/child::*', $NS)) {
|
||||
ForEach ($Child in $XMLProductSection.SelectNodes('//ns:ProductSection/child::*', $NS)) {
|
||||
[void]$Child.ParentNode.RemoveChild($Child)
|
||||
}
|
||||
Write-Host "Destroyed pre-existing children in 'ProductSection'"
|
||||
@ -124,15 +214,13 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||
ForEach ($Property in $Category.ProductProperties) {
|
||||
$XMLProperty = $XML.CreateElement('Property', $XML.DocumentElement.xmlns)
|
||||
|
||||
$XMLPropertyAttrKey = $XML.CreateAttribute('key', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrKey.Value = $Property.Key
|
||||
$XMLPropertyAttrType = $XML.CreateAttribute('type', $XML.DocumentElement.ovf)
|
||||
[void]$XMLProperty.SetAttribute('key', $NS.LookupNamespace('ovf'), $Property.Key)
|
||||
Switch -regex ($Property.Type) {
|
||||
'^boolean' {
|
||||
$XMLPropertyAttrType.Value = 'boolean'
|
||||
[void]$XMLProperty.SetAttribute('type', $NS.LookupNamespace('ovf'), 'boolean')
|
||||
}
|
||||
'^int' {
|
||||
$XMLPropertyAttrType.Value = 'uint8'
|
||||
[void]$XMLProperty.SetAttribute('type', $NS.LookupNamespace('ovf'), 'uint16')
|
||||
$Qualifiers = @()
|
||||
If ($Property.Type -match '^int\((\d*)\.\.(\d*)\)') {
|
||||
If ($Matches[1]) {
|
||||
@ -141,23 +229,16 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||
If ($Matches[2]) {
|
||||
$Qualifiers += "MaxValue($($Matches[2]))"
|
||||
}
|
||||
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||
[void]$XMLProperty.SetAttribute('qualifiers', $NS.LookupNamespace('ovf'), $Qualifiers -join ' ')
|
||||
}
|
||||
}
|
||||
'^ip' {
|
||||
$XMLPropertyAttrType.Value = 'string'
|
||||
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.vmw)
|
||||
$XMLPropertyAttrQualifiers.Value = 'Ip'
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||
[void]$XMLProperty.SetAttribute('type', $NS.LookupNamespace('ovf'), 'string')
|
||||
[void]$XMLProperty.SetAttribute('qualifiers', $NS.LookupNamespace('vmw'), 'Ip')
|
||||
}
|
||||
'^password' {
|
||||
$XMLPropertyAttrType.Value = 'string'
|
||||
$XMLPropertyAttrPassword = $XML.CreateAttribute('password', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrPassword.Value = 'true'
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrPassword)
|
||||
|
||||
[void]$XMLProperty.SetAttribute('type', $NS.LookupNamespace('ovf'), 'string')
|
||||
[void]$XMLProperty.SetAttribute('password', $NS.LookupNamespace('ovf'), 'true')
|
||||
$Qualifiers = @()
|
||||
If ($Property.Type -match '^password\((\d*)\.\.(\d*)\)') {
|
||||
If ($Matches[1]) {
|
||||
@ -166,13 +247,11 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||
If ($Matches[2]) {
|
||||
$Qualifiers += "MaxLen($($Matches[2]))"
|
||||
}
|
||||
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||
[void]$XMLProperty.SetAttribute('qualifiers', $NS.LookupNamespace('ovf'), $Qualifiers -join ' ')
|
||||
}
|
||||
}
|
||||
'^string' {
|
||||
$XMLPropertyAttrType.Value = 'string'
|
||||
[void]$XMLProperty.SetAttribute('type', $NS.LookupNamespace('ovf'), 'string')
|
||||
$Qualifiers = @()
|
||||
If ($Property.Type -match '^string\((\d*)\.\.(\d*)\)') {
|
||||
If ($Matches[1]) {
|
||||
@ -181,28 +260,19 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||
If ($Matches[2]) {
|
||||
$Qualifiers += "MaxLen($($Matches[2]))"
|
||||
}
|
||||
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrQualifiers.Value = $Qualifiers -join ' '
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||
[void]$XMLProperty.SetAttribute('qualifiers', $NS.LookupNamespace('ovf'), $Qualifiers -join ' ')
|
||||
} ElseIf ($Property.Type -match '^string\[(.*)\]') {
|
||||
$XMLPropertyAttrQualifiers = $XML.CreateAttribute('qualifiers', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrQualifiers.Value = "ValueMap{$($Matches[1] -replace '","', '", "')}"
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrQualifiers)
|
||||
[void]$XMLProperty.SetAttribute('qualifiers', $NS.LookupNamespace('ovf'), "ValueMap{$($Matches[1] -replace '","', '", "')}")
|
||||
}
|
||||
}
|
||||
}
|
||||
$XMLPropertyAttrUserConfigurable = $XML.CreateAttribute('userConfigurable', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrUserConfigurable.Value = "$([boolean]$Property.UserConfigurable)".ToLower()
|
||||
$XMLPropertyAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf)
|
||||
[void]$XMLProperty.SetAttribute('userConfigurable', $NS.LookupNamespace('ovf'), "$([boolean]$Property.UserConfigurable)".ToLower())
|
||||
|
||||
If ($Property.Type -eq 'boolean') {
|
||||
$XMLPropertyAttrValue.Value = "$([boolean]$Property.DefaultValue)".ToLower()
|
||||
[void]$XMLProperty.SetAttribute('value', $NS.LookupNamespace('ovf'), "$([boolean]$Property.DefaultValue)".ToLower())
|
||||
} Else {
|
||||
$XMLPropertyAttrValue.Value = $Property.DefaultValue
|
||||
[void]$XMLProperty.SetAttribute('value', $NS.LookupNamespace('ovf'), $Property.DefaultValue)
|
||||
}
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrKey)
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrType)
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrUserConfigurable)
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrValue)
|
||||
|
||||
If ($Property.Label) {
|
||||
$XMLPropertyLabel = $XML.CreateElement('Label', $XML.DocumentElement.xmlns)
|
||||
@ -216,30 +286,19 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||
}
|
||||
|
||||
If (($Property.Configurations.Count -eq 1) -and ($Property.Configurations -eq '*')) {
|
||||
$XMLPropertyAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrConfiguration.Value = $OVFConfig.DeploymentConfigurations.Id -join ' '
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrConfiguration)
|
||||
[void]$XMLProperty.SetAttribute('configuration', $NS.LookupNamespace('ovf'), $OVFConfig.DeploymentConfigurations.Id -join ' ')
|
||||
} ElseIf ($Property.Configurations.Count -gt 0) {
|
||||
$XMLPropertyAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrConfiguration.Value = $Property.Configurations -join ' '
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrConfiguration)
|
||||
[void]$XMLProperty.SetAttribute('configuration', $NS.LookupNamespace('ovf'), $Property.Configurations -join ' ')
|
||||
}
|
||||
|
||||
If ($Property.Value.Count -eq 1) {
|
||||
$XMLPropertyAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf)
|
||||
$XMLPropertyAttrValue.Value = $Property.Value
|
||||
[void]$XMLProperty.Attributes.Append($XMLPropertyAttrValue)
|
||||
[void]$XMLProperty.SetAttribute('value', $NS.LookupNamespace('ovf'), $Property.Value)
|
||||
} ElseIf ($Property.Value.Count -gt 1) {
|
||||
ForEach ($Value in $Property.Value) {
|
||||
$XMLValue = $XML.CreateElement('Value', $XML.DocumentElement.xmlns)
|
||||
|
||||
$XMLValueAttrValue = $XML.CreateAttribute('value', $XML.DocumentElement.ovf)
|
||||
$XMLValueAttrValue.Value = $Value
|
||||
$XMLValueAttrConfiguration = $XML.CreateAttribute('configuration', $XML.DocumentElement.ovf)
|
||||
$XMLValueAttrConfiguration.Value = $Value
|
||||
|
||||
[void]$XMLValue.Attributes.Append($XMLValueAttrValue)
|
||||
[void]$XMLValue.Attributes.Append($XMLValueAttrConfiguration)
|
||||
[void]$XMLValue.SetAttribute('value', $NS.LookupNamespace('ovf'), $Value)
|
||||
[void]$XMLValue.SetAttribute('configuration', $NS.LookupNamespace('ovf'), $Value)
|
||||
|
||||
[void]$XMLProperty.AppendChild($XMLValue)
|
||||
}
|
||||
@ -250,4 +309,4 @@ ForEach ($Category in $OVFConfig.PropertyCategories) {
|
||||
Write-Host "Inserted $($Category.ProductProperties.Count) new node(s) into 'ProductSection'"
|
||||
}
|
||||
|
||||
$XML.Save($SourceFile.FullName)
|
||||
$XML.Save($SourceFile.FullName)
|
@ -1,19 +1,26 @@
|
||||
DeploymentConfigurations:
|
||||
- Id: domainmember
|
||||
Label: Domain member
|
||||
Description: Windows 10 client joined to an Active Directory domain
|
||||
- Id: standalone
|
||||
Label: Stand-alone
|
||||
Description: Stand-alone Windows 10 client
|
||||
- Id: small
|
||||
Label: 'Ubuntu Server 20.04 [SMALL: 1 vCPU/2GB RAM]'
|
||||
Description: Ubuntu Server 20.04.x
|
||||
Size:
|
||||
CPU: 1
|
||||
Memory: 2048
|
||||
- Id: large
|
||||
Label: 'Ubuntu Server 20.04 [LARGE: 4 vCPU/8GB RAM]'
|
||||
Description: Ubuntu Server 20.04.x
|
||||
Size:
|
||||
CPU: 4
|
||||
Memory: 8192
|
||||
DynamicDisks: []
|
||||
PropertyCategories:
|
||||
- Name: 0) Deployment information
|
||||
ProductProperties:
|
||||
- Key: deployment.type
|
||||
Type: string
|
||||
Value:
|
||||
- domainmember
|
||||
- standalone
|
||||
UserConfigurable: false
|
||||
# - Name: 0) Deployment information
|
||||
# ProductProperties:
|
||||
# - Key: deployment.type
|
||||
# Type: string
|
||||
# Value:
|
||||
# - small
|
||||
# - large
|
||||
# UserConfigurable: false
|
||||
- Name: 1) Operating System
|
||||
ProductProperties:
|
||||
- Key: guestinfo.hostname
|
||||
@ -23,21 +30,26 @@ PropertyCategories:
|
||||
DefaultValue: ''
|
||||
Configurations: '*'
|
||||
UserConfigurable: true
|
||||
- Key: guestinfo.administratorpw
|
||||
- Key: guestinfo.rootpw
|
||||
Type: password(7..)
|
||||
Label: Local administrator password*
|
||||
Description: Must meet password complexity rules
|
||||
DefaultValue: password
|
||||
Configurations:
|
||||
- standalone
|
||||
Label: Local root password*
|
||||
Description: ''
|
||||
DefaultValue: ''
|
||||
Configurations: '*'
|
||||
UserConfigurable: true
|
||||
- Key: guestinfo.rootsshkey
|
||||
Type: password(1..)
|
||||
Label: Local root SSH public key*
|
||||
Description: This line should start with 'ssh-rsa AAAAB3N'
|
||||
DefaultValue: ''
|
||||
Configurations: '*'
|
||||
UserConfigurable: true
|
||||
- Key: guestinfo.ntpserver
|
||||
Type: string(1..)
|
||||
Label: Time server*
|
||||
Description: A comma-separated list of timeservers
|
||||
DefaultValue: 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org
|
||||
Configurations:
|
||||
- standalone
|
||||
Configurations: '*'
|
||||
UserConfigurable: true
|
||||
- Name: 2) Networking
|
||||
ProductProperties:
|
||||
@ -69,32 +81,6 @@ PropertyCategories:
|
||||
DefaultValue: ''
|
||||
Configurations: '*'
|
||||
UserConfigurable: true
|
||||
- Name: 3) Active Directory membership
|
||||
ProductProperties:
|
||||
- Key: addsconfig.domainname
|
||||
Type: string(1..)
|
||||
Label: Domain name*
|
||||
Description: Must be able to be resolved through provided DNS server
|
||||
DefaultValue: example.org
|
||||
Configurations:
|
||||
- domainmember
|
||||
UserConfigurable: true
|
||||
- Key: addsconfig.username
|
||||
Type: string(1..)
|
||||
Label: Domain account username*
|
||||
Description: ''
|
||||
DefaultValue: username
|
||||
Configurations:
|
||||
- domainmember
|
||||
UserConfigurable: true
|
||||
- Key: addsconfig.password
|
||||
Type: password(1..)
|
||||
Label: Domain account password*
|
||||
Description: ''
|
||||
DefaultValue: password
|
||||
Configurations:
|
||||
- domainmember
|
||||
UserConfigurable: true
|
||||
AdvancedOptions:
|
||||
- Key: appliance.name
|
||||
Value: "{{ appliance.name }}"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
# No parameters
|
||||
)
|
||||
|
||||
# Create scheduled task
|
||||
& schtasks.exe /Create /TN 'FirstBoot' /SC ONSTART /RU SYSTEM /TR "powershell.exe -file C:\Payload\Apply-FirstBootConfig.ps1"
|
@ -1,244 +0,0 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
# No parameters
|
||||
)
|
||||
|
||||
$SetLocationSplat = @{
|
||||
Path = $PSScriptRoot
|
||||
}
|
||||
Set-Location @SetLocationSplat
|
||||
|
||||
$NewEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
New-EventLog @NewEventLogSplat
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Information'
|
||||
EventID = 1
|
||||
Message = "FirstBoot sequence initiated [working directory: '$PWD']"
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
|
||||
$VMwareToolsExecutable = "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe"
|
||||
|
||||
[xml]$ovfEnv = & $VMwareToolsExecutable --cmd "info-get guestinfo.ovfEnv" | Out-String
|
||||
$ovfProperties = $ovfEnv.ChildNodes.NextSibling.PropertySection.Property
|
||||
|
||||
$ovfPropertyValues = @{}
|
||||
foreach ($ovfProperty in $ovfProperties) {
|
||||
$ovfPropertyValues[$ovfProperty.key] = $ovfProperty.Value
|
||||
}
|
||||
|
||||
# Check for mandatory values
|
||||
Switch ($ovfPropertyValues['deployment.type']) {
|
||||
'domainmember' {
|
||||
$MandatoryProperties, $MissingProperties = @('guestinfo.hostname', 'guestinfo.ipaddress', 'guestinfo.prefixlength', 'guestinfo.gateway', 'addsconfig.domainname', 'addsconfig.username', 'addsconfig.password'), @()
|
||||
}
|
||||
'standalone' {
|
||||
$MandatoryProperties, $MissingProperties = @('guestinfo.hostname', 'guestinfo.ipaddress', 'guestinfo.prefixlength', 'guestinfo.gateway', 'guestinfo.administratorpw', 'guestinfo.ntpserver'), @()
|
||||
}
|
||||
default {
|
||||
# Mandatory values missing, cannot provision.
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Error'
|
||||
EventID = 66
|
||||
Message = "Unexpected or no value set for property 'deployment.type', cannot provision."
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
& schtasks.exe /Change /TN 'FirstBoot' /DISABLE
|
||||
Stop-Computer -Force
|
||||
Exit
|
||||
}
|
||||
}
|
||||
ForEach ($Property in $MandatoryProperties) {
|
||||
If (!$ovfPropertyValues[$Property]) {
|
||||
$MissingProperties += $Property
|
||||
}
|
||||
}
|
||||
If ($MissingProperties.Length -gt 0) {
|
||||
# Mandatory values missing, cannot provision.
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Error'
|
||||
EventID = 66
|
||||
Message = "Missing values for mandatory properties $(($MissingProperties | ForEach-Object {"'{0}'" -f $_}) -join ', '), cannot provision."
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
& schtasks.exe /Change /TN 'FirstBoot' /DISABLE
|
||||
Stop-Computer -Force
|
||||
Exit
|
||||
}
|
||||
|
||||
# Set hostname and description
|
||||
If ($Env:ComputerName -ne $ovfPropertyValues['guestinfo.hostname']) {
|
||||
$RenameComputerSplat = @{
|
||||
NewName = $ovfPropertyValues['guestinfo.hostname']
|
||||
Force = $True
|
||||
Confirm = $False
|
||||
}
|
||||
Rename-Computer @RenameComputerSplat
|
||||
$SetCimInstanceSplat = @{
|
||||
InputObject = (Get-CimInstance -ClassName 'Win32_OperatingSystem')
|
||||
Property = @{
|
||||
Description = $ovfPropertyValues['guestinfo.hostname']
|
||||
}
|
||||
}
|
||||
Set-CimInstance @SetCimInstanceSplat
|
||||
|
||||
# Restart the computer to apply changes
|
||||
Restart-Computer -Force
|
||||
Exit
|
||||
}
|
||||
|
||||
# Configure network interface
|
||||
If ((Get-WmiObject -Class 'Win32_NetworkAdapterConfiguration').IPAddress -NotContains $ovfPropertyValues['guestinfo.ipaddress']) {
|
||||
$NewNetIPAddressSplat = @{
|
||||
InterfaceAlias = (Get-NetAdapter).Name
|
||||
AddressFamily = 'IPv4'
|
||||
IPAddress = $ovfPropertyValues['guestinfo.ipaddress']
|
||||
PrefixLength = $ovfPropertyValues['guestinfo.prefixlength']
|
||||
DefaultGateway = $ovfPropertyValues['guestinfo.gateway']
|
||||
}
|
||||
$IPAddress = New-NetIPAddress @NewNetIPAddressSplat
|
||||
|
||||
# Wait for network connection to become available
|
||||
$Timestamp, $TimeoutMinutes = (Get-Date), 5
|
||||
Do {
|
||||
If ($Timestamp.AddMinutes($TimeoutMinutes) -lt (Get-Date)) {
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Warning'
|
||||
EventID = 13
|
||||
Message = "Timeout after $($TimeoutMinutes) minutes waiting for network connection to become available."
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
Break
|
||||
}
|
||||
|
||||
Start-Sleep -Milliseconds 250
|
||||
|
||||
$GetNetIPAddressSplat = @{
|
||||
IPAddress = $ovfPropertyValues['guestinfo.ipaddress']
|
||||
InterfaceIndex = $IPAddress.InterfaceIndex
|
||||
AddressFamily = 'IPv4'
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
} Until ((Get-NetIPAddress @GetNetIPAddressSplat).AddressState -eq 'Preferred')
|
||||
|
||||
$OldErrorActionPreference, $ErrorActionPreference = $ErrorActionPreference, 'SilentlyContinue'
|
||||
$TestNetConnectionSplat = @{
|
||||
ComputerName = ([IPAddress]$ovfPropertyValues['guestinfo.dnsserver']).IPAddressToString
|
||||
InformationLevel = 'Quiet'
|
||||
}
|
||||
$SetDnsClientServerAddressSplat = @{
|
||||
InterfaceAlias = (Get-NetAdapter).Name
|
||||
ServerAddresses = If (
|
||||
[boolean]($ovfPropertyValues['guestinfo.dnsserver'] -as [IPaddress]) -and (Test-NetConnection @TestNetConnectionSplat)) {
|
||||
($ovfPropertyValues['guestinfo.dnsserver'])
|
||||
} else {
|
||||
('127.0.0.1')
|
||||
}
|
||||
Validate = $False
|
||||
}
|
||||
Set-DnsClientServerAddress @SetDnsClientServerAddressSplat
|
||||
$ErrorActionPreference, $OldErrorActionPreference = $OldErrorActionPreference, $NULL
|
||||
}
|
||||
|
||||
Switch ($ovfPropertyValues['deployment.type']) {
|
||||
'domainmember' {
|
||||
# Join Active Directory domain as member
|
||||
If (!(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain) {
|
||||
$AddComputerSplat = @{
|
||||
DomainName = $ovfPropertyValues['addsconfig.domainname']
|
||||
Credential = New-Object System.Management.Automation.PSCredential(
|
||||
$ovfPropertyValues['addsconfig.username'],
|
||||
(ConvertTo-SecureString $ovfPropertyValues['addsconfig.password'] -AsPlainText -Force)
|
||||
)
|
||||
# OUPath = $ovfPropertyValues['addsconfig.organizationalunit']
|
||||
Restart = $True
|
||||
Force = $True
|
||||
Confirm = $False
|
||||
}
|
||||
Add-Computer @AddComputerSplat
|
||||
|
||||
# Previous cmdlet performs a reboot on completion; so these are commented out
|
||||
# Restart-Computer -Force
|
||||
# Exit
|
||||
}
|
||||
}
|
||||
'standalone' {
|
||||
# Change password of built-in Administrator
|
||||
$BuiltinAdministrator = (Get-LocalUser | Where-Object {$_.SID -match '-500'})
|
||||
$ConvertToSecureStringSplat = @{
|
||||
String = $ovfPropertyValues['guestinfo.administratorpw']
|
||||
AsPlainText = $True
|
||||
Force = $True
|
||||
}
|
||||
$SetLocalUserSplat = @{
|
||||
InputObject = $BuiltinAdministrator
|
||||
Password = ConvertTo-SecureString @ConvertToSecureStringSplat
|
||||
PasswordNeverExpires = $True
|
||||
AccountNeverExpires = $True
|
||||
### This setting is not allowed on the last administrator
|
||||
# UserMayChangePassword = $False
|
||||
Confirm = $False
|
||||
}
|
||||
Set-LocalUser @SetLocalUserSplat
|
||||
|
||||
$EnableLocalUserSplat = @{
|
||||
InputObject = $BuiltinAdministrator
|
||||
Confirm = $False
|
||||
}
|
||||
Enable-LocalUser @EnableLocalUserSplat
|
||||
}
|
||||
}
|
||||
|
||||
# Iterate through and invoke all payload scripts
|
||||
#! TODO: add registry values to determine which scripts have already been invoked (in case of intermediate reboots)
|
||||
$GetItemSplat = @{
|
||||
Path = "$($PSScriptRoot)\Scripts\*.ps1"
|
||||
}
|
||||
ForEach ($Script in (Get-Item @GetItemSplat)) {
|
||||
Try {
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Information'
|
||||
EventID = 4
|
||||
Message = "Running script: '$($Script.FullName)'"
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
& $Script.FullName -Parameter $ovfPropertyValues
|
||||
}
|
||||
Catch {
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Error'
|
||||
EventID = 66
|
||||
Message = @"
|
||||
Error occurred while executing script '$($Script.Name)':
|
||||
$($_.Exception.Message)
|
||||
"@
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
}
|
||||
}
|
||||
|
||||
$WriteEventLogSplat = @{
|
||||
LogName = 'Application'
|
||||
Source = 'FirstBoot'
|
||||
EntryType = 'Information'
|
||||
EventID = 42
|
||||
Message = 'FirstBoot sequence applied and finished'
|
||||
}
|
||||
Write-EventLog @WriteEventLogSplat
|
||||
& schtasks.exe /Change /TN 'FirstBoot' /DISABLE
|
Reference in New Issue
Block a user