Skip to content

Commit 46c820e

Browse files
committed
test images: uses nanoserver
Using Windows nanoserver container images as a base instead of the current Windows servercore image will reduce the image size by about ~10x. However, the nanoserver image lacks several things we need: - netapi32.dll - powershell - certain powershell commands - chocolatey cannot be used When building the nanoserver images, we are going to use a Windows servercore helper, in which we are going to install the necessary dependencies, and then copy them over to our nanoserver image, including necessary DLLs. Other notable changes include: - switch from wget to curl (wget was a powershell alias). - implement in code getting the DNS suffix list and DNS server list. - reimplement getting file permissions for mounttest.
1 parent 8d30a5f commit 46c820e

File tree

13 files changed

+252
-75
lines changed

13 files changed

+252
-75
lines changed

build/dependencies.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
dependencies:
22
# agnhost: bump this one first
33
- name: "agnhost"
4-
version: "2.22"
4+
version: "2.23"
55
refPaths:
66
- path: test/images/agnhost/VERSION
77
match: \d.\d

test/images/agnhost/Dockerfile_windows

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# limitations under the License.
1414

1515
ARG BASEIMAGE
16+
ARG REGISTRY
17+
FROM $REGISTRY/windows-image-builder-helper:1.0 as helper
1618
FROM $BASEIMAGE
1719

1820
# from dnsutils image
@@ -24,18 +26,17 @@ FROM $BASEIMAGE
2426
# - curl, nc: used by a lot of e2e tests (inherited from BASEIMAGE)
2527
# from iperf image
2628
# install necessary packages: iperf
27-
ENV chocolateyUseWindowsCompression false
28-
RUN powershell -Command "\
29-
iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')); \
30-
choco feature disable --name showDownloadProgress; \
31-
choco install bind-toolsonly --version 9.10.3 -y
29+
COPY --from=helper /dig /dig
30+
COPY --from=helper /Windows/System32/netapi32.dll /Windows/System32/netapi32.dll
31+
32+
RUN setx /M PATH "C:\dig\;%PATH%
3233
RUN powershell -Command "\
33-
wget -uri 'https://github.com/coredns/coredns/releases/download/v1.5.0/coredns_1.5.0_windows_amd64.tgz' -OutFile C:\coredns.tgz;\
34-
tar -xzvf C:\coredns.tgz;\
34+
curl.exe -L 'https://github.com/coredns/coredns/releases/download/v1.5.0/coredns_1.5.0_windows_amd64.tgz' -o C:\coredns.tgz;\
35+
tar.exe -xzvf C:\coredns.tgz;\
3536
Remove-Item C:\coredns.tgz"
3637

3738
RUN powershell -Command "\
38-
wget -uri 'https://iperf.fr/download/windows/iperf-2.0.9-win64.zip' -OutFile C:\iperf.zip;\
39+
curl.exe -L 'https://iperf.fr/download/windows/iperf-2.0.9-win64.zip' -o C:\iperf.zip;\
3940
Expand-Archive -Path C:\iperf.zip -DestinationPath C:\ -Force;\
4041
Rename-Item C:\iperf-2.0.9-win64 C:\iperf;\
4142
Remove-Item C:\iperf.zip"
@@ -53,6 +54,9 @@ RUN mkdir C:\uploads
5354
ADD porter/localhost.crt localhost.crt
5455
ADD porter/localhost.key localhost.key
5556

57+
# from mounttest
58+
ADD mounttest/filePermissions.ps1 filePermissions.ps1
59+
5660
ADD agnhost agnhost
5761

5862
# needed for the entrypoint-tester related tests. Some of the entrypoint-tester related tests

test/images/agnhost/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.22
1+
2.23

test/images/agnhost/agnhost.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import (
5151
func main() {
5252
rootCmd := &cobra.Command{
5353
Use: "app",
54-
Version: "2.22",
54+
Version: "2.23",
5555
}
5656

5757
rootCmd.AddCommand(auditproxy.CmdAuditProxy)

test/images/agnhost/dns/BUILD

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ go_library(
1515
importpath = "k8s.io/kubernetes/test/images/agnhost/dns",
1616
deps = [
1717
"//vendor/github.com/spf13/cobra:go_default_library",
18-
],
18+
] + select({
19+
"@io_bazel_rules_go//go/platform:windows": [
20+
"//vendor/golang.org/x/sys/windows:go_default_library",
21+
"//vendor/golang.org/x/sys/windows/registry:go_default_library",
22+
],
23+
"//conditions:default": [],
24+
}),
1925
)
2026

2127
filegroup(
Lines changed: 113 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build windows
2+
13
/*
24
Copyright 2019 The Kubernetes Authors.
35
@@ -17,40 +19,131 @@ limitations under the License.
1719
package dns
1820

1921
import (
20-
"bytes"
21-
"os/exec"
22+
"fmt"
2223
"strings"
24+
"syscall"
25+
"unsafe"
26+
27+
"golang.org/x/sys/windows"
28+
"golang.org/x/sys/windows/registry"
2329
)
2430

25-
const etcHostsFile = "C:/Windows/System32/drivers/etc/hosts"
31+
const (
32+
etcHostsFile = "C:/Windows/System32/drivers/etc/hosts"
33+
netRegistry = `System\CurrentControlSet\Services\TCPIP\Parameters`
34+
netIfacesRegistry = `System\CurrentControlSet\Services\TCPIP\Parameters\Interfaces`
35+
maxHostnameLen = 128
36+
maxDomainNameLen = 128
37+
maxScopeIDLen = 256
38+
)
2639

27-
func getDNSSuffixList() []string {
28-
output := runCommand("powershell", "-Command", "(Get-DnsClient)[0].SuffixSearchList")
29-
if len(output) > 0 {
30-
return strings.Split(output, "\r\n")
31-
}
40+
// FixedInfo information: https://docs.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-fixed_info_w2ksp1
41+
type FixedInfo struct {
42+
HostName [maxHostnameLen + 4]byte
43+
DomainName [maxDomainNameLen + 4]byte
44+
CurrentDNSServer *syscall.IpAddrString
45+
DNSServerList syscall.IpAddrString
46+
NodeType uint32
47+
ScopeID [maxScopeIDLen + 4]byte
48+
EnableRouting uint32
49+
EnableProxy uint32
50+
EnableDNS uint32
51+
}
52+
53+
var (
54+
// GetNetworkParams can be found in iphlpapi.dll
55+
// see: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getnetworkparams?redirectedfrom=MSDN
56+
iphlpapidll = windows.MustLoadDLL("iphlpapi.dll")
57+
procGetNetworkParams = iphlpapidll.MustFindProc("GetNetworkParams")
58+
)
3259

33-
panic("Could not find DNS search list!")
60+
func elemInList(elem string, list []string) bool {
61+
for _, e := range list {
62+
if e == elem {
63+
return true
64+
}
65+
}
66+
return false
3467
}
3568

36-
func getDNSServerList() []string {
37-
output := runCommand("powershell", "-Command", "(Get-DnsClientServerAddress).ServerAddresses")
38-
if len(output) > 0 {
39-
return strings.Split(output, "\r\n")
69+
func getRegistryValue(reg, key string) string {
70+
regKey, err := registry.OpenKey(registry.LOCAL_MACHINE, reg, registry.QUERY_VALUE)
71+
if err != nil {
72+
return ""
4073
}
74+
defer regKey.Close()
4175

42-
panic("Could not find DNS Server list!")
76+
regValue, _, err := regKey.GetStringValue(key)
77+
if err != nil {
78+
return ""
79+
}
80+
return regValue
4381
}
4482

45-
func runCommand(name string, arg ...string) string {
46-
var out bytes.Buffer
47-
cmd := exec.Command(name, arg...)
48-
cmd.Stdout = &out
83+
// getDNSSuffixList reads DNS config file and returns the list of configured DNS suffixes
84+
func getDNSSuffixList() []string {
85+
// We start with the general suffix list that apply to all network connections.
86+
allSuffixes := []string{}
87+
suffixes := getRegistryValue(netRegistry, "SearchList")
88+
if suffixes != "" {
89+
allSuffixes = strings.Split(suffixes, ",")
90+
}
4991

50-
err := cmd.Run()
92+
// Then we append the network-specific DNS suffix lists.
93+
regKey, err := registry.OpenKey(registry.LOCAL_MACHINE, netIfacesRegistry, registry.ENUMERATE_SUB_KEYS)
5194
if err != nil {
5295
panic(err)
5396
}
97+
defer regKey.Close()
5498

55-
return strings.TrimSpace(out.String())
99+
ifaces, err := regKey.ReadSubKeyNames(0)
100+
if err != nil {
101+
panic(err)
102+
}
103+
for _, iface := range ifaces {
104+
suffixes := getRegistryValue(fmt.Sprintf("%s\\%s", netIfacesRegistry, iface), "SearchList")
105+
if suffixes == "" {
106+
continue
107+
}
108+
for _, suffix := range strings.Split(suffixes, ",") {
109+
if !elemInList(suffix, allSuffixes) {
110+
allSuffixes = append(allSuffixes, suffix)
111+
}
112+
}
113+
}
114+
115+
return allSuffixes
116+
}
117+
118+
func getNetworkParams() *FixedInfo {
119+
// We don't know how big we should make the byte buffer, but the call will tell us by
120+
// setting the size afterwards.
121+
var size int
122+
buffer := make([]byte, 1)
123+
procGetNetworkParams.Call(
124+
uintptr(unsafe.Pointer(&buffer[0])),
125+
uintptr(unsafe.Pointer(&size)),
126+
)
127+
128+
buffer = make([]byte, size)
129+
procGetNetworkParams.Call(
130+
uintptr(unsafe.Pointer(&buffer[0])),
131+
uintptr(unsafe.Pointer(&size)),
132+
)
133+
134+
info := (*FixedInfo)(unsafe.Pointer(&buffer[0]))
135+
return info
136+
}
137+
138+
func getDNSServerList() []string {
139+
dnsServerList := []string{}
140+
fixedInfo := getNetworkParams()
141+
list := &(fixedInfo.DNSServerList)
142+
143+
for list != nil {
144+
dnsServer := strings.TrimRight(string(list.IpAddress.String[:]), "\x00")
145+
dnsServerList = append(dnsServerList, dnsServer)
146+
list = list.Next
147+
}
148+
return dnsServerList
56149
}

test/images/agnhost/mounttest/filePermissions.ps1

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,59 +28,41 @@ $EXECUTE_PERMISSIONS = 0x0001 -bor 0x0020
2828

2929

3030
function GetFilePermissions($path) {
31-
$objPath = "Win32_LogicalFileSecuritySetting='$path'"
32-
$output = Invoke-WmiMethod -Namespace root/cimv2 -Path $objPath -Name GetSecurityDescriptor
33-
34-
if ($output.ReturnValue -ne 0) {
35-
$retVal = $output.ReturnValue
36-
Write-Error "GetSecurityDescriptor invocation failed with code: $retVal"
37-
exit 1
38-
}
39-
40-
$fileSD = $output.Descriptor
41-
$fileOwnerGroup = $fileSD.Group
42-
$fileOwner = $fileSD.Owner
43-
44-
if ($fileOwnerGroup.Name -eq $null -and $fileOwnerGroup.Domain -eq $null) {
45-
# the file owner's group is not recognized. Check if the Owner itself is
46-
# a group, and if so, default the group to it.
47-
net user $fileOwner.Name > $null 2> $null
48-
if (-not $?) {
49-
$fileOwnerGroup = $fileOwner
50-
}
51-
52-
}
31+
$fileAcl = Get-Acl -Path $path
32+
$fileOwner = $fileAcl.Owner
33+
$fileGroup = $fileAcl.Group
5334

5435
$userMask = 0
5536
$groupMask = 0
5637
$otherMask = 0
5738

58-
foreach ($ace in $fileSD.DACL) {
59-
$mask = 0
60-
if ($ace.AceType -ne 0) {
61-
# not an Allow ACE, skip.
39+
foreach ($rule in $fileAcl.Access) {
40+
if ($rule.AccessControlType -ne [Security.AccessControl.AccessControlType]::Allow) {
41+
# not an allow rule, skipping.
6242
continue
6343
}
6444

45+
$mask = 0
46+
$rights = $rule.FileSystemRights.value__
6547
# convert mask.
66-
if ( ($ace.AccessMask -band $READ_PERMISSIONS) -eq $READ_PERMISSIONS ) {
48+
if ( ($rights -band $READ_PERMISSIONS) -eq $READ_PERMISSIONS ) {
6749
$mask = $mask -bor 4
6850
}
69-
if ( ($ace.AccessMask -band $WRITE_PERMISSIONS) -eq $WRITE_PERMISSIONS ) {
51+
if ( ($rights -band $WRITE_PERMISSIONS) -eq $WRITE_PERMISSIONS ) {
7052
$mask = $mask -bor 2
7153
}
72-
if ( ($ace.AccessMask -band $EXECUTE_PERMISSIONS) -eq $EXECUTE_PERMISSIONS ) {
54+
if ( ($rights -band $EXECUTE_PERMISSIONS) -eq $EXECUTE_PERMISSIONS ) {
7355
$mask = $mask -bor 1
7456
}
7557

7658
# detect mask type.
77-
if ($ace.Trustee.Equals($fileOwner)) {
59+
if ($rule.IdentityReference.Value.Equals($fileOwner)) {
7860
$userMask = $mask
7961
}
80-
if ($ace.Trustee.Equals($fileOwnerGroup)) {
62+
if ($rule.IdentityReference.Value.Equals($fileGroup)) {
8163
$groupMask = $mask
8264
}
83-
if ($ace.Trustee.Name.ToLower() -eq "users") {
65+
if ($rule.IdentityReference.Value.ToLower().Contains("users")) {
8466
$otherMask = $mask
8567
}
8668
}

test/images/busybox/BASEIMAGE

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
windows/amd64/1809=mcr.microsoft.com/windows/servercore:ltsc2019
2-
windows/amd64/1903=mcr.microsoft.com/windows/servercore:1903
3-
windows/amd64/1909=mcr.microsoft.com/windows/servercore:1909
1+
windows/amd64/1809=mcr.microsoft.com/windows/nanoserver:1809
2+
windows/amd64/1903=mcr.microsoft.com/windows/nanoserver:1903
3+
windows/amd64/1909=mcr.microsoft.com/windows/nanoserver:1909

test/images/busybox/Dockerfile_windows

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,57 @@
1515
ARG BASEIMAGE
1616
from $BASEIMAGE as prep
1717

18-
ENV CURL_VERSION 7.57.0
18+
ENV CURL_VERSION=7.57.0 \
19+
PS_VERSION=6.2.0
1920
WORKDIR /curl
2021
ADD https://skanthak.homepage.t-online.de/download/curl-$CURL_VERSION.cab curl.cab
21-
RUN expand /R curl.cab /F:* .
22+
ADD https://github.com/PowerShell/PowerShell/releases/download/v$PS_VERSION/PowerShell-$PS_VERSION-win-x64.zip /PowerShell/powershell.zip
23+
ADD https://eternallybored.org/misc/netcat/netcat-win32-1.12.zip /netcat//netcat.zip
24+
25+
USER ContainerAdministrator
26+
RUN expand /R curl.cab /F:* . &\
27+
cd C:\PowerShell &\
28+
tar.exe -xf powershell.zip &\
29+
del powershell.zip &\
30+
mklink powershell.exe pwsh.exe &\
31+
cd C:\netcat &\
32+
tar.exe -xf netcat.zip &\
33+
del netcat.zip
2234

2335
FROM $BASEIMAGE
2436

25-
COPY --from=prep /curl/AMD64 /curl
26-
COPY --from=prep /curl/CURL.LIC /curl
37+
COPY --from=prep /curl/AMD64 /curl/CURL.LIC /curl/
38+
COPY --from=prep ["/PowerShell", "/Program Files/PowerShell"]
39+
COPY --from=prep /netcat/nc64.exe /bin/nc.exe
2740
ADD https://github.com/kubernetes-sigs/windows-testing/raw/master/images/busybox/busybox.exe /bin/busybox.exe
28-
ADD https://github.com/diegocr/netcat/raw/master/nc.exe /bin/nc.exe
2941
ADD hostname /bin/hostname.exe
42+
3043
USER ContainerAdministrator
3144
RUN FOR /f "tokens=*" %i IN ('C:\bin\busybox --list') DO mklink C:\bin\%i.exe C:\bin\busybox.exe
32-
RUN setx /M PATH "C:\bin;C:\curl\;%PATH%" &\
45+
# Set the path
46+
RUN setx /M PATH "C:\bin;C:\curl\;%PATH%;C:\Program Files\PowerShell;" &\
3347
mkdir C:\tmp
48+
49+
# Copy PowerShell Core from the installer container
50+
ENV ProgramFiles="C:\Program Files" \
51+
# set a fixed location for the Module analysis cache
52+
LOCALAPPDATA="C:\Users\ContainerAdministrator\AppData\Local" \
53+
PSModuleAnalysisCachePath="$LOCALAPPDATA\Microsoft\Windows\PowerShell\docker\ModuleAnalysisCache" \
54+
# Persist %PSCORE% ENV variable for user convenience
55+
PSCORE="$ProgramFiles\PowerShell\pwsh.exe"
56+
57+
# intialize powershell module cache
58+
RUN powershell \
59+
-NoLogo \
60+
-NoProfile \
61+
-Command " \
62+
$stopTime = (get-date).AddMinutes(15); \
63+
$ErrorActionPreference = 'Stop' ; \
64+
$ProgressPreference = 'SilentlyContinue' ; \
65+
while(!(Test-Path -Path $env:PSModuleAnalysisCachePath)) { \
66+
Write-Host "'Waiting for $env:PSModuleAnalysisCachePath'" ; \
67+
if((get-date) -gt $stopTime) { throw 'timout expired'} \
68+
Start-Sleep -Seconds 6 ; \
69+
}"
70+
3471
ENTRYPOINT ["cmd.exe", "/s", "/c"]

0 commit comments

Comments
 (0)