-
-
Notifications
You must be signed in to change notification settings - Fork 179
Add Windows image packaging scripts #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
5287ce7
Add Windows container support
slide e02cd6f
Add Makefile
slide a7e310a
Add Jenkinsfile
slide 90a9d02
Add "make" file for Windows builds
slide 95ffbe7
Add endless loop to stop container from exiting
slide 40febd7
Add PasswordNeverExpires attribute to user
slide 9a046d6
Fix label and use powershell step
slide File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # Based on code developed by Josh Rickard (@MS_dministrator) and Thom Schumacher (@driberif) | ||
| # Location: https://gist.github.com/crshnbrn66/7e81bf20408c05ddb2b4fdf4498477d8 | ||
|
|
||
| #function to register a native method | ||
| function Register-NativeMethod | ||
| { | ||
| [CmdletBinding()] | ||
| [Alias()] | ||
| [OutputType([int])] | ||
| Param | ||
| ( | ||
| # Param1 help description | ||
| [Parameter(Mandatory=$true, | ||
| ValueFromPipelineByPropertyName=$true, | ||
| Position=0)] | ||
| [string]$dll, | ||
|
|
||
| # Param2 help description | ||
| [Parameter(Mandatory=$true, | ||
| ValueFromPipelineByPropertyName=$true, | ||
| Position=1)] | ||
| [string] | ||
| $methodSignature | ||
| ) | ||
|
|
||
| $script:nativeMethods += [PSCustomObject]@{ Dll = $dll; Signature = $methodSignature; } | ||
| } | ||
|
|
||
| #function to add native method | ||
| function Add-NativeMethods | ||
| { | ||
| [CmdletBinding()] | ||
| [Alias()] | ||
| [OutputType([int])] | ||
| Param($typeName = 'NativeMethods') | ||
|
|
||
| $nativeMethodsCode = $script:nativeMethods | ForEach-Object { " | ||
| [DllImport(`"$($_.Dll)`")] | ||
| public static extern $($_.Signature); | ||
| " } | ||
|
|
||
| Add-Type @" | ||
| using System; | ||
| using System.Text; | ||
| using System.Runtime.InteropServices; | ||
| public static class $typeName { | ||
| $nativeMethodsCode | ||
| } | ||
| "@ | ||
| } | ||
|
|
||
| #Main function to create the new user profile | ||
| function New-UserWithProfile { | ||
| [CmdletBinding()] | ||
| [Alias()] | ||
| [OutputType([int])] | ||
| Param | ||
| ( | ||
| # Param1 help description | ||
| [Parameter(Mandatory=$true, | ||
| ValueFromPipelineByPropertyName=$true, | ||
| Position=0)] | ||
| [string]$UserName, | ||
|
|
||
| # Param2 help description | ||
| [Parameter(ValueFromPipelineByPropertyName=$true, | ||
| Position=1)] | ||
| [SecureString] | ||
| $Password, | ||
|
|
||
| [Parameter(Mandatory=$false, | ||
| ValueFromPipelineByPropertyName=$true, | ||
| Position=2)] | ||
| [string] | ||
| $Description | ||
| ) | ||
|
|
||
| Write-Verbose "Creating local user $Username"; | ||
|
|
||
| try | ||
| { | ||
| if($null -eq $Password) { | ||
| New-LocalUser -Name $UserName -NoPassword -Description "$Description" -AccountNeverExpires | ||
| } else { | ||
| New-LocalUser -Name $UserName -Password $Password -Description "$Description" -AccountNeverExpires | ||
| } | ||
| } | ||
| catch | ||
| { | ||
| Write-Error $_.Exception.Message; | ||
| break; | ||
| } | ||
| $methodName = 'UserEnvCP' | ||
| $script:nativeMethods = @(); | ||
|
|
||
| if (-not ([System.Management.Automation.PSTypeName]$MethodName).Type) | ||
| { | ||
| Register-NativeMethod "userenv.dll" "int CreateProfile([MarshalAs(UnmanagedType.LPWStr)] string pszUserSid,` | ||
| [MarshalAs(UnmanagedType.LPWStr)] string pszUserName,` | ||
| [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszProfilePath, uint cchProfilePath)"; | ||
|
|
||
| Add-NativeMethods -typeName $MethodName; | ||
| } | ||
|
|
||
| $localUser = New-Object System.Security.Principal.NTAccount("$UserName"); | ||
| $userSID = $localUser.Translate([System.Security.Principal.SecurityIdentifier]); | ||
| $sb = new-object System.Text.StringBuilder(260); | ||
| $pathLen = $sb.Capacity; | ||
|
|
||
| Write-Verbose "Creating user profile for $Username"; | ||
|
|
||
| try | ||
| { | ||
| [UserEnvCP]::CreateProfile($userSID.Value, $Username, $sb, $pathLen) | Out-Null; | ||
| } | ||
| catch | ||
| { | ||
| Write-Error $_.Exception.Message; | ||
| break; | ||
| } | ||
|
|
||
| $profilePath = $sb.ToString() | ||
| Write-Verbose "Profile created at $profilePath" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # escape=` | ||
|
|
||
| # The MIT License | ||
| # | ||
| # Copyright (c) 2019, Alex Earl | ||
| # | ||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| # of this software and associated documentation files (the "Software"), to deal | ||
| # in the Software without restriction, including without limitation the rights | ||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| # copies of the Software, and to permit persons to whom the Software is | ||
| # furnished to do so, subject to the following conditions: | ||
| # | ||
| # The above copyright notice and this permission notice shall be included in | ||
| # all copies or substantial portions of the Software. | ||
| # | ||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| # THE SOFTWARE. | ||
|
|
||
| ARG WINDOWS_DOCKER_TAG=1809 | ||
|
|
||
| FROM openjdk:8-jdk-windowsservercore-$WINDOWS_DOCKER_TAG | ||
| LABEL MAINTAINER="Alex Earl <slide.o.mix@gmail.com>" | ||
|
|
||
| SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] | ||
|
|
||
| ARG user=jenkins | ||
|
|
||
| ARG JENKINS_AGENT_HOME=C:/Users/${user} | ||
|
|
||
| ARG OPENSSH_VERSION=v8.0.0.0p1-Beta | ||
|
|
||
| ENV JENKINS_AGENT_USER ${user} | ||
|
|
||
| ENV JENKINS_AGENT_HOME ${JENKINS_AGENT_HOME} | ||
|
|
||
| COPY CreateProfile.psm1 C:/ | ||
|
|
||
| #create jenkins user | ||
| RUN Import-Module -Force C:/CreateProfile.psm1 ; ` | ||
| New-UserWithProfile -UserName $env:user -Description 'Jenkins Agent User' ; ` | ||
| Remove-Item -Force C:/CreateProfile.psm1 ; ` | ||
| Set-LocalUser -Name $env:user -PasswordNeverExpires $true ; ` | ||
| New-Item -Type Directory -Path "C:\ProgramData\Jenkins" | Out-Null | ||
|
|
||
| # setup SSH server | ||
| RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; ` | ||
| Invoke-WebRequest -Uri "https://github.com/PowerShell/Win32-OpenSSH/releases/download/${env:OPENSSH_VERSION}/OpenSSH-Win64.zip -OutFile C:/openssh.zip -UseBasicParsing ; ` | ||
| Expand-Archive c:/openssh.zip 'C:/Program Files' ; ` | ||
| Remove-Item C:/openssh.zip ; ` | ||
| $env:PATH = '{0};{1}' -f $env:PATH,'C:\Program Files\OpenSSH-Win64' ; ` | ||
| & 'C:/Program Files/OpenSSH-Win64/Install-SSHd.ps1' ; ` | ||
| New-Item -Type Directory -Path 'C:\ProgramData\ssh' | Out-Null ; ` | ||
| Copy-Item 'C:\Program Files\OpenSSH-Win64\sshd_config_default' 'C:\ProgramData\ssh\sshd_config' ; ` | ||
| $content = Get-Content -Path "C:\ProgramData\ssh\sshd_config" ; ` | ||
| $content | ForEach-Object { $_ -replace '#PermitRootLogin.*','PermitRootLogin no' ` | ||
| -replace '#PasswordAuthentication.*','PasswordAuthentication no' ` | ||
| -replace '#PermitEmptyPasswords.*','PermitEmptyPasswords no' ` | ||
| -replace '#PubkeyAuthentication.*','PubkeyAuthentication yes' ` | ||
| -replace '#SyslogFacility.*','SyslogFacility LOCAL0' ` | ||
| -replace '#LogLevel.*','LogLevel DEBUG3' ` | ||
| -replace 'Match Group administrators','' ` | ||
| -replace '(\s*)AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys','' ` | ||
| } | ` | ||
| Set-Content -Path "C:\ProgramData\ssh\sshd_config" ; ` | ||
| Add-Content -Path "C:\ProgramData\ssh\sshd_config" -Value 'ChallengeResponseAuthentication no' ; ` | ||
| Add-Content -Path "C:\ProgramData\ssh\sshd_config" -Value 'HostKeyAgent \\.\pipe\openssh-ssh-agent' ; ` | ||
| New-Item -Path HKLM:\SOFTWARE -Name OpenSSH -Force | Out-Null ; ` | ||
| New-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell -Value 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -PropertyType string -Force | Out-Null | ||
|
|
||
| VOLUME "${JENKINS_AGENT_HOME}" "C:\Users\${user}\AppData\Local\Temp" | ||
| WORKDIR "${JENKINS_AGENT_HOME}" | ||
|
|
||
| COPY setup-sshd.ps1 C:/ProgramData/Jenkins/setup-sshd.ps1 | ||
|
|
||
| EXPOSE 22 | ||
|
|
||
| ENTRYPOINT ["powershell.exe", "-NoExit", "-Command", "& C:/ProgramData/Jenkins/setup-sshd.ps1"] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* NOTE: this Pipeline mainly aims at catching mistakes (wrongly formed Dockerfile, etc.) | ||
| * This Pipeline is *not* used for actual image publishing. | ||
| * This is currently handled through Automated Builds using standard Docker Hub feature | ||
| */ | ||
| pipeline { | ||
| agent { label 'linux' } | ||
|
|
||
| options { | ||
| timeout(time: 2, unit: 'MINUTES') | ||
| buildDiscarder(logRotator(daysToKeepStr: '10')) | ||
| timestamps() | ||
| } | ||
|
|
||
| triggers { | ||
| pollSCM('H/24 * * * *') // once a day in case some hooks are missed | ||
| } | ||
|
|
||
| stages { | ||
| stage('Build Docker Image') { | ||
| parallel { | ||
| stage('Windows') { | ||
| agent { | ||
| label "windock" | ||
| } | ||
| steps { | ||
| deleteDir() | ||
| checkout scm | ||
| powershell "& ./make.ps1" | ||
| } | ||
| } | ||
| stage('Linux') { | ||
| agent { | ||
| label "docker&&linux" | ||
| } | ||
| steps { | ||
| deleteDir() | ||
| checkout scm | ||
| sh "make build" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // vim: ft=groovy |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| ROOT:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) | ||
| IMAGE_NAME:=jenkins4eval/ssh-slave:test | ||
|
|
||
| build: | ||
| docker build -t ${IMAGE_NAME} . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| if([System.String]::IsNullOrWhiteSpace($env:IMAGE_NAME)) { | ||
| $env:IMAGE_NAME='jenkins4eval/ssh-agent:test-windows' | ||
| } | ||
|
|
||
| & docker build -f Dockerfile-windows -t $env:IMAGE_NAME . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| # The MIT License | ||
| # | ||
| # Copyright (c) 2019, Alex Earl | ||
| # | ||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| # of this software and associated documentation files (the "Software"), to deal | ||
| # in the Software without restriction, including without limitation the rights | ||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| # copies of the Software, and to permit persons to whom the Software is | ||
| # furnished to do so, subject to the following conditions: | ||
| # | ||
| # The above copyright notice and this permission notice shall be included in | ||
| # all copies or substantial portions of the Software. | ||
| # | ||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| # THE SOFTWARE. | ||
|
|
||
| # Usage: | ||
| # docker run jenkins/ssh-agent:windows <public key> | ||
| # or | ||
| # docker run -e "JENKINS_SLAVE_SSH_PUBKEY=<public key>" jenkins/ssh-agent:windows | ||
|
|
||
| function Write-Key($Key) { | ||
| # this writes the key and sets the permissions correctly for pubkey auth | ||
| $sshDir = '{0}\.ssh' -f $env:JENKINS_AGENT_HOME | ||
| $authorizedKeys = Join-Path $sshDir 'authorized_keys' | ||
| New-Item -Type Directory -Path $sshDir | Out-Null | ||
| icacls.exe $sshDir /setowner ${env:JENKINS_AGENT_USER} | Out-Null | ||
| icacls.exe $sshDir /grant "${env:JENKINS_AGENT_USER}:(CI)(OI)(F)" /grant "administrators:(CI)(OI)(F)" | Out-Null | ||
| icacls.exe $sshDir /inheritance:r | Out-Null | ||
|
|
||
| Set-Content -Path $authorizedKeys -Value "$Key" -Encoding UTF8 | ||
| icacls.exe $authorizedKeys /setowner ${env:JENKINS_AGENT_USER} | Out-Null | ||
| } | ||
|
|
||
| # Even though we created a profile, the NTUSER.DAT file is missing | ||
| # this needs to be in the directory or Windows will not load | ||
| # the profile | ||
| if(!(Test-Path (Join-Path $env:JENKINS_AGENT_HOME 'NTUSER.DAT'))) { | ||
| Copy-Item -Path 'C:\Users\Default\NTUSER.DAT' -Destination (Join-Path $env:JENKINS_AGENT_HOME 'NTUSER.DAT') | ||
| } | ||
|
|
||
| # Give the user Full Access to the home directory | ||
| icacls.exe $env:JENKINS_AGENT_HOME /grant "${env:JENKINS_AGENT_USER}:(CI)(OI)(F)" | Out-Null | ||
|
|
||
| if($env:JENKINS_SLAVE_SSH_PUBKEY -match "^ssh-.*") { | ||
| Write-Key $env:JENKINS_SLAVE_SSH_PUBKEY | ||
| } | ||
|
|
||
| if($args.Length -gt 0) { | ||
| if($args[0] -match "^ssh-.*") { | ||
| Write-Key "$($args[0]) $($args[1]) $($args[2])" | ||
| $null, $null, $null, $args = $args | ||
| } else { | ||
| & "$args" | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
| # ensure variables passed to docker container are also exposed to ssh sessions | ||
| Get-ChildItem env: | ForEach-Object { setx /m $_.Name $_.Value | Out-Null } | ||
|
|
||
| Start-Service sshd | ||
| while($true) { | ||
| # if we don't do this endless loop, the container exits | ||
| Start-Sleep -Seconds 60 | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps enabling Tls12 could be upstreamed?
Here is a PowerShell script version of it, could be converted to Docker run :)