-
Notifications
You must be signed in to change notification settings - Fork 722
Expand file tree
/
Copy pathstart-runner.ps1
More file actions
206 lines (165 loc) · 8.19 KB
/
start-runner.ps1
File metadata and controls
206 lines (165 loc) · 8.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
## Retrieve instance metadata
function Tag-InstanceWithRunnerId {
Write-Host "Checking for .runner file to extract agent ID"
$runnerFilePath = "$pwd\.runner"
if (-not (Test-Path $runnerFilePath)) {
Write-Host "Warning: .runner file not found"
return $true
}
Write-Host "Found .runner file, extracting agent ID"
try {
$runnerConfig = Get-Content $runnerFilePath | ConvertFrom-Json
$agentId = $runnerConfig.agentId
if (-not $agentId -or $agentId -eq $null) {
Write-Host "Warning: Could not extract agent ID from .runner file"
return $true
}
Write-Host "Tagging instance with GitHub runner agent ID: $agentId"
$tagResult = aws ec2 create-tags --region "$Region" --resources "$InstanceId" --tags "Key=ghr:github_runner_id,Value=$agentId" 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "Successfully tagged instance with agent ID: $agentId"
return $true
} else {
Write-Host "Warning: Failed to tag instance with agent ID - $tagResult"
return $true
}
}
catch {
Write-Host "Warning: Error processing .runner file - $($_.Exception.Message)"
return $true
}
}
## Retrieve instance metadata
Write-Host "Retrieving TOKEN from AWS API"
$token=Invoke-RestMethod -Method PUT -Uri "http://169.254.169.254/latest/api/token" -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "180"}
if ( ! $token ) {
$retrycount=0
do {
echo "Failed to retrieve token. Retrying in 5 seconds."
Start-Sleep 5
$token=Invoke-RestMethod -Method PUT -Uri "http://169.254.169.254/latest/api/token" -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "180"}
$retrycount=$retrycount + 1
if ( $retrycount -gt 40 )
{
break
}
} until ($token)
}
$ami_id=Invoke-RestMethod -Uri "http://169.254.169.254/latest/meta-data/ami-id" -Headers @{"X-aws-ec2-metadata-token" = $token}
$metadata=Invoke-RestMethod -Uri "http://169.254.169.254/latest/dynamic/instance-identity/document" -Headers @{"X-aws-ec2-metadata-token" = $token}
$Region = $metadata.region
Write-Host "Retrieved REGION from AWS API ($Region)"
$InstanceId = $metadata.instanceId
Write-Host "Retrieved InstanceId from AWS API ($InstanceId)"
$tags=aws ec2 describe-tags --region "$Region" --filters "Name=resource-id,Values=$InstanceId" | ConvertFrom-Json
Write-Host "Retrieved tags from AWS API"
$environment=$tags.Tags.where( {$_.Key -eq 'ghr:environment'}).value
Write-Host "Retrieved ghr:environment tag - ($environment)"
$runner_name_prefix=$tags.Tags.where( {$_.Key -eq 'ghr:runner_name_prefix'}).value
Write-Host "Retrieved ghr:runner_name_prefix tag - ($runner_name_prefix)"
$ssm_config_path=$tags.Tags.where( {$_.Key -eq 'ghr:ssm_config_path'}).value
Write-Host "Retrieved ghr:ssm_config_path tag - ($ssm_config_path)"
$parameters=$(aws ssm get-parameters-by-path --path "$ssm_config_path" --region "$Region" --query "Parameters[*].{Name:Name,Value:Value}") | ConvertFrom-Json
Write-Host "Retrieved parameters from AWS SSM"
$run_as=$parameters.where( {$_.Name -eq "$ssm_config_path/run_as"}).value
Write-Host "Retrieved $ssm_config_path/run_as parameter - ($run_as)"
$enable_cloudwatch_agent=$parameters.where( {$_.Name -eq "$ssm_config_path/enable_cloudwatch"}).value
Write-Host "Retrieved $ssm_config_path/enable_cloudwatch parameter - ($enable_cloudwatch_agent)"
$agent_mode=$parameters.where( {$_.Name -eq "$ssm_config_path/agent_mode"}).value
Write-Host "Retrieved $ssm_config_path/agent_mode parameter - ($agent_mode)"
$disable_default_labels=$parameters.where( {$_.Name -eq "$ssm_config_path/disable_default_labels"}).value
Write-Host "Retrieved $ssm_config_path/disable_default_labels parameter - ($disable_default_labels)"
$enable_jit_config=$parameters.where( {$_.Name -eq "$ssm_config_path/enable_jit_config"}).value
Write-Host "Retrieved $ssm_config_path/enable_jit_config parameter - ($enable_jit_config)"
$token_path=$parameters.where( {$_.Name -eq "$ssm_config_path/token_path"}).value
Write-Host "Retrieved $ssm_config_path/token_path parameter - ($token_path)"
if ($enable_cloudwatch_agent -eq "true")
{
Write-Host "Enabling CloudWatch Agent"
& 'C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1' -a fetch-config -m ec2 -s -c "ssm:$ssm_config_path/cloudwatch_agent_config_runner"
}
## Configure the runner
Write-Host "Get GH Runner config from AWS SSM"
$config = $null
$i = 0
do {
$config = (aws ssm get-parameters --names "$token_path/$InstanceId" --with-decryption --region $Region --query "Parameters[*].{Name:Name,Value:Value}" | ConvertFrom-Json)[0].value
Write-Host "Waiting for GH Runner config to become available in AWS SSM ($i/30)"
Start-Sleep 1
$i++
} while (($null -eq $config) -and ($i -lt 30))
Write-Host "Delete GH Runner token from AWS SSM"
aws ssm delete-parameter --name "$token_path/$InstanceId" --region $Region
# Create or update user
if (-not($run_as)) {
Write-Host "No user specified, using default ec2-user account"
$run_as="ec2-user"
}
Add-Type -AssemblyName "System.Web"
$password = [System.Web.Security.Membership]::GeneratePassword(24, 4)
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$username = $run_as
if (!(Get-LocalUser -Name $username -ErrorAction Ignore)) {
New-LocalUser -Name $username -Password $securePassword
Write-Host "Created new user ($username)"
}
else {
Set-LocalUser -Name $username -Password $securePassword
Write-Host "Changed password for user ($username)"
}
# Add user to groups
foreach ($group in @("Administrators", "docker-users")) {
if ((Get-LocalGroup -Name "$group" -ErrorAction Ignore) -and
!(Get-LocalGroupMember -Group "$group" -Member $username -ErrorAction Ignore)) {
Add-LocalGroupMember -Group "$group" -Member $username
Write-Host "Added $username to $group group"
}
}
# Disable User Access Control (UAC)
# TODO investigate if this is needed or if its overkill - https://github.com/github-aws-runners/terraform-aws-github-runner/issues/1505
Set-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name ConsentPromptBehaviorAdmin -Value 0 -Force
Write-Host "Disabled User Access Control (UAC)"
$runnerExtraOptions = ""
if ($disable_default_labels -eq "true") {
$runnerExtraOptions += "--no-default-labels"
}
if ($enable_jit_config -eq "false" -or $agent_mode -ne "ephemeral") {
$configCmd = ".\config.cmd --unattended --name $runner_name_prefix$InstanceId --work `"_work`" $runnerExtraOptions $config"
Write-Host "Configure GH Runner (non ephmeral / no JIT) as user $run_as"
Invoke-Expression $configCmd
# Tag instance with GitHub runner agent ID for non-JIT runners
Tag-InstanceWithRunnerId
}
$jsonBody = @(
@{
group='Runner Image'
detail="AMI id: $ami_id"
}
)
ConvertTo-Json -InputObject $jsonBody | Set-Content -Path "$pwd\.setup_info"
Write-Host "Starting the runner in $agent_mode mode"
Write-Host "Starting runner after $(((get-date) - (gcim Win32_OperatingSystem).LastBootUpTime).tostring("hh':'mm':'ss''"))"
if ($agent_mode -eq "ephemeral") {
if ($enable_jit_config -eq "true") {
Write-Host "Starting with jit config"
Invoke-Expression ".\run.cmd --jitconfig $${config}"
}
else {
Write-Host "Starting without jit config"
Invoke-Expression ".\run.cmd"
}
Write-Host "Runner has finished"
if ($enable_cloudwatch_agent)
{
Write-Host "Stopping CloudWatch Agent"
& 'C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1' -a stop
}
Write-Host "Terminating instance"
aws ec2 terminate-instances --instance-ids "$InstanceId" --region "$Region"
} else {
Write-Host "Installing the runner as a service"
$action = New-ScheduledTaskAction -WorkingDirectory "$pwd" -Execute "run.cmd"
$trigger = Get-CimClass "MSFT_TaskRegistrationTrigger" -Namespace "Root/Microsoft/Windows/TaskScheduler"
Register-ScheduledTask -TaskName "runnertask" -Action $action -Trigger $trigger -User $username -Password $password -RunLevel Highest -Force
Write-Host "Starting runner after $(((get-date) - (gcim Win32_OperatingSystem).LastBootUpTime).tostring("hh':'mm':'ss''"))"
}