From 1c4e8b49fdbf65a4bb33cce1fe3cdde4a1c66276 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Sun, 2 Apr 2023 23:56:56 +0200 Subject: [PATCH 1/8] wip --- protocol/misc.go | 1 + protocol/runner_admin.go | 28 ++++++++++++++ runnerconfiguration/add.go | 25 +++++++++++- runnerconfiguration/common.go | 71 ++++++++++++++++++++++++----------- 4 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 protocol/runner_admin.go diff --git a/protocol/misc.go b/protocol/misc.go index 79474d7..810e86d 100644 --- a/protocol/misc.go +++ b/protocol/misc.go @@ -19,6 +19,7 @@ type GitHubAuthResult struct { TenantURL string `json:"url"` TokenSchema string `json:"token_schema"` Token string `json:"token"` + UseV2FLow string `json:"use_v2_flow"` } type TaskOrchestrationPlanReference struct { diff --git a/protocol/runner_admin.go b/protocol/runner_admin.go new file mode 100644 index 0000000..f7c8904 --- /dev/null +++ b/protocol/runner_admin.go @@ -0,0 +1,28 @@ +package protocol + +type Runner struct { + Name string `json:"name"` + Id int32 `json:"id"` + Authorization struct { + AuthorizationUrl string `json:"authorization_url"` + ServerUrl string `json:"server_url"` + ClientId string `json:"client_id"` + } `json:"authorization"` +} + +type RunnerGroup struct { + Id int32 `json:"id,omitempty"` + Name string `json:"name,omitempty"` + IsDefault bool `json:"default,omitempty"` + IsHosted bool `json:"is_hosted,omitempty"` +} + +type RunnerGroupList struct { + RunnerGroups []RunnerGroup `json:"runner_groups"` + Count int `json:"total_count"` +} + +type ListRunnersResponse struct { + TotalCount int `json:"total_count"` + Runners []Runner `json:"runners"` +} \ No newline at end of file diff --git a/runnerconfiguration/add.go b/runnerconfiguration/add.go index 875284c..a77bb10 100644 --- a/runnerconfiguration/add.go +++ b/runnerconfiguration/add.go @@ -63,10 +63,33 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey Token: res.Token, Trace: config.Trace, } + + getRunnerGroups := func() (*TaskAgentPools, error) { + return vssConnection.GetAgentPools() + } + if res.UseV2FLow { + apiBuilder, err := NewGithubApiUrlBuilder(config.URL) + if err != nil { + return nil, fmt.Errorf("invalid Url: %v\n", config.URL) + } + getRunnerGroups = func() (*protocol.TaskAgentPools, error) { + runnerGroupsURL, err := apiBuilder.AbsoluteApiUrl("actions/runner-groups") + if err != nil { + return nil, err + } + runnerGroups := &protocol.RunnerGroupList{} + err = vssConnection.RequestWithContext2(context.Background(), "GET", runnerGroupsURL, "", nil, runnerGroups) + if err != nil { + return nil, err + } + poolList := &protocol.TaskAgentPools{} + return poolList, nil + } + } { taskAgentPool := "" taskAgentPools := []string{} - _taskAgentPools, err := vssConnection.GetAgentPools() + _taskAgentPools, err := getRunnerGroups() if err != nil { return nil, fmt.Errorf("failed to configure runner: %v\n", err) } diff --git a/runnerconfiguration/common.go b/runnerconfiguration/common.go index 1032ade..8e29114 100644 --- a/runnerconfiguration/common.go +++ b/runnerconfiguration/common.go @@ -74,34 +74,62 @@ type RunnerSettings struct { Instances []*RunnerInstance } -func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent string, apiEndpoint string, survey Survey) (*protocol.GitHubAuthResult, error) { - registerUrl, err := url.Parse(config.URL) +type GithubApiUrlBuilder struct { + URL *url.URL + ApiScope string +} + +func NewGithubApiUrlBuilder(URL string) (*GithubApiUrlBuilder, error) { + baseUrl, err := url.Parse(URL) if err != nil { - return nil, fmt.Errorf("invalid Url: %v\n", config.URL) + return nil, err } - apiscope := "/" - if strings.ToLower(registerUrl.Host) == "github.com" { - registerUrl.Host = "api." + registerUrl.Host + apiBuilder := &GithubApiUrlBuilder{ + URL: baseUrl + } + if strings.EqualFold(apiBuilder.URL.Host, "github.com") || strings.HasSuffix(strings.ToLower(apiBuilder.URL.Host), ".ghe.com") { + apiBuilder.URL.Host = "api." + apiBuilder.URL.Host } else { - apiscope = "/api/v3" + apiBuilder.ApiScope = "/api/v3" } + return apiBuilder, nil +} +func (apiBuilder *GithubApiUrlBuilder) AbsoluteApiUrl(path string) string { + url := *apiBuilder.URL + url.Path = path.Join(apiBuilder.ApiScope, path) + return url.String() +} + +func (apiBuilder *GithubApiUrlBuilder) ScopedApiUrl(path string) (string, error) { + paths := strings.Split(strings.TrimPrefix(URL.Path, "/"), "/") + url := *apiBuilder.URL + if len(paths) == 1 { + url.Path = path.Join(apiscope, "orgs", paths[0], path) + } else if len(paths) == 2 { + scope := "repos" + if strings.EqualFold(paths[0], "enterprises") { + scope = "" + } + url.Path = path.Join(apiscope, scope, paths[0], paths[1], path) + } else { + return "", fmt.Errorf("unsupported registration url") + } + return url.String(), nil +} + +func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent string, apiEndpoint string, survey Survey) (*protocol.GitHubAuthResult, error) { + apiBuilder, err := NewGithubApiUrlBuilder(config.URL) + if err != nil { + return nil, fmt.Errorf("invalid Url: %v\n", config.URL) + } if len(config.Token) == 0 { if len(config.Pat) > 0 { - paths := strings.Split(strings.TrimPrefix(registerUrl.Path, "/"), "/") - url := *registerUrl - if len(paths) == 1 { - url.Path = path.Join(apiscope, "orgs", paths[0], "actions/runners", apiEndpoint) - } else if len(paths) == 2 { - scope := "repos" - if strings.EqualFold(paths[0], "enterprises") { - scope = "" - } - url.Path = path.Join(apiscope, scope, paths[0], paths[1], "actions/runners", apiEndpoint) - } else { - return nil, fmt.Errorf("unsupported registration url") + url, err := apiBuilder.ScopedApiUrl(path.Join("actions/runners", apiEndpoint)) + if err != nil { + return nil, err } - req, _ := http.NewRequest("POST", url.String(), nil) + req, _ := http.NewRequest("POST", url, nil) req.SetBasicAuth("github", config.Pat) req.Header.Add("Accept", "application/vnd.github.v3+json") resp, err := c.Do(req) @@ -126,7 +154,6 @@ func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent strin if len(config.Token) == 0 { return nil, fmt.Errorf("no runner registration token provided") } - registerUrl.Path = path.Join(apiscope, "actions/runner-registration") buf := new(bytes.Buffer) req := &protocol.RunnerAddRemove{} @@ -136,7 +163,7 @@ func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent strin if err := enc.Encode(req); err != nil { return nil, err } - finalregisterUrl := registerUrl.String() + finalregisterUrl := apiBuilder.AbsoluteApiUrl("actions/runner-registration") r, _ := http.NewRequest("POST", finalregisterUrl, buf) r.Header["Authorization"] = []string{"RemoteAuth " + config.Token} From 100ddbab63bc4d174d5733be2e676d6106a0c3bc Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 9 Mar 2025 11:38:25 +0100 Subject: [PATCH 2/8] Reworkv2 register --- actionsrunner/runner.go | 2 +- protocol/runner_admin.go | 12 +- protocol/task_agent.go | 4 +- runnerconfiguration/add.go | 113 +++++++++++++++--- runnerconfiguration/common.go | 2 +- .../compat/actions_runner_compat.go | 48 +++----- runnerconfiguration/remove.go | 42 +++++-- 7 files changed, 158 insertions(+), 65 deletions(-) diff --git a/actionsrunner/runner.go b/actionsrunner/runner.go index b6af2b7..f8e8f61 100644 --- a/actionsrunner/runner.go +++ b/actionsrunner/runner.go @@ -50,7 +50,7 @@ type RunnerEnvironment interface { func (run *RunRunner) Run(runnerenv RunnerEnvironment, listenerctx context.Context, corectx context.Context) error { settings := run.Settings for i := 0; i < len(settings.Instances); i++ { - if err := settings.Instances[i].EnshurePKey(); err != nil { + if err := settings.Instances[i].EnsurePKey(); err != nil { return err } } diff --git a/protocol/runner_admin.go b/protocol/runner_admin.go index f7c8904..66e0c3b 100644 --- a/protocol/runner_admin.go +++ b/protocol/runner_admin.go @@ -2,10 +2,10 @@ package protocol type Runner struct { Name string `json:"name"` - Id int32 `json:"id"` + Id int64 `json:"id"` Authorization struct { - AuthorizationUrl string `json:"authorization_url"` - ServerUrl string `json:"server_url"` + AuthorizationURL string `json:"authorization_url"` + ServerURL string `json:"server_url"` ClientId string `json:"client_id"` } `json:"authorization"` } @@ -23,6 +23,6 @@ type RunnerGroupList struct { } type ListRunnersResponse struct { - TotalCount int `json:"total_count"` - Runners []Runner `json:"runners"` -} \ No newline at end of file + TotalCount int `json:"total_count"` + Runners []Runner `json:"runners"` +} diff --git a/protocol/task_agent.go b/protocol/task_agent.go index f8270f1..3c1e031 100644 --- a/protocol/task_agent.go +++ b/protocol/task_agent.go @@ -35,7 +35,7 @@ type TaskAgent struct { Authorization TaskAgentAuthorization Labels []AgentLabel MaxParallelism int - ID int + ID int64 Name string Version string OSDescription string @@ -45,6 +45,8 @@ type TaskAgent struct { CreatedOn string Ephemeral bool `json:",omitempty"` DisableUpdate bool `json:",omitempty"` + // Just a convenient way to store the URL, not part of the spec + ServerV2URL string `json:",omitempty"` } type TaskAgents struct { diff --git a/runnerconfiguration/add.go b/runnerconfiguration/add.go index 3608746..b08f542 100644 --- a/runnerconfiguration/add.go +++ b/runnerconfiguration/add.go @@ -7,6 +7,7 @@ import ( "crypto/x509" "encoding/base64" "encoding/binary" + "encoding/xml" "fmt" "os" "runtime" @@ -36,7 +37,7 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey WorkFolder: config.WorkFolder, } if config.Ephemeral && len(settings.Instances) > 0 || containsEphemeralConfiguration(settings) { - return nil, fmt.Errorf("ephemeral is not supported for multi runners, runner already configured.") + return nil, fmt.Errorf("ephemeral is not supported for multi runners, runner already configured") } if len(config.URL) == 0 { if !config.Unattended { @@ -66,17 +67,29 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey Token: res.Token, Trace: config.Trace, } + if res.UseV2FLow { + vssConnection = &protocol.VssConnection{ + AuthHeader: "RemoteAuth " + config.Token, + Trace: config.Trace, + Client: c, + } + } getRunnerGroups := func() (*protocol.TaskAgentPools, error) { return vssConnection.GetAgentPools() } + var apiBuilder *GithubApiUrlBuilder if res.UseV2FLow { - apiBuilder, err := NewGithubApiUrlBuilder(config.URL) + var err error + apiBuilder, err = NewGithubApiUrlBuilder(config.URL) if err != nil { return nil, fmt.Errorf("invalid Url: %v", config.URL) } getRunnerGroups = func() (*protocol.TaskAgentPools, error) { - runnerGroupsURL := apiBuilder.AbsoluteApiUrl("actions/runner-groups") + runnerGroupsURL, err := apiBuilder.ScopedApiUrl("actions/runner-groups") + if err != nil { + return nil, err + } runnerGroups := &protocol.RunnerGroupList{} err = vssConnection.RequestWithContext2(context.Background(), "GET", runnerGroupsURL, "", nil, runnerGroups) if err != nil { @@ -91,7 +104,7 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey taskAgentPools := []string{} _taskAgentPools, err := getRunnerGroups() if err != nil { - return nil, fmt.Errorf("failed to configure runner: %v\n", err) + return nil, fmt.Errorf("failed to configure runner: %v", err) } for _, val := range _taskAgentPools.Value { if !val.IsHosted { @@ -116,7 +129,7 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey } } if vssConnection.PoolID < 0 { - return nil, fmt.Errorf("runner Pool %v not found\n", taskAgentPool) + return nil, fmt.Errorf("runner Pool %v not found", taskAgentPool) } } key, _ := rsa.GenerateKey(rand.Reader, 2048) @@ -165,20 +178,40 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey taskAgent.Ephemeral = config.Ephemeral taskAgent.DisableUpdate = config.DisableUpdate { - err := vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "POST", map[string]string{ - "poolId": fmt.Sprint(vssConnection.PoolID), - }, map[string]string{}, taskAgent, taskAgent) + var err error + if auth.UseV2FLow { + err = registerOrReplaceRunnerV2(taskAgent, config, vssConnection, apiBuilder, false) + } else { + err = vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "POST", map[string]string{ + "poolId": fmt.Sprint(vssConnection.PoolID), + }, map[string]string{}, taskAgent, taskAgent) + } if err != nil { if !config.Replace { - return nil, fmt.Errorf("failed to create taskAgent: %v\n", err.Error()) + return nil, fmt.Errorf("failed to create taskAgent: %v", err.Error()) } // Try replaceing runner if creation failed taskAgents := &protocol.TaskAgents{} - err := vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "GET", map[string]string{ - "poolId": fmt.Sprint(vssConnection.PoolID), - }, map[string]string{}, nil, taskAgents) + if auth.UseV2FLow { + resv2 := &protocol.ListRunnersResponse{} + runnersURL, _ := apiBuilder.ScopedApiUrl("actions/runners") + err = vssConnection.RequestWithContext2(context.Background(), "GET", runnersURL, "", nil, resv2) + if err == nil { + for _, runner := range resv2.Runners { + taskAgents.Value = append(taskAgents.Value, protocol.TaskAgent{ + ID: runner.Id, + Name: runner.Name, + }) + } + taskAgents.Count = int64(len(taskAgents.Value)) + } + } else { + err = vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "GET", map[string]string{ + "poolId": fmt.Sprint(vssConnection.PoolID), + }, map[string]string{}, nil, taskAgents) + } if err != nil { - return nil, fmt.Errorf("failed to update taskAgent: %v\n", err.Error()) + return nil, fmt.Errorf("failed to update taskAgent: %v", err.Error()) } invalid := true for i := 0; i < len(taskAgents.Value); i++ { @@ -191,12 +224,16 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey if invalid { return nil, fmt.Errorf("failed to update taskAgent: Failed to find agent") } - err = vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "PUT", map[string]string{ - "poolId": fmt.Sprint(vssConnection.PoolID), - "agentId": fmt.Sprint(taskAgent.ID), - }, map[string]string{}, taskAgent, taskAgent) + if auth.UseV2FLow { + err = registerOrReplaceRunnerV2(taskAgent, config, vssConnection, apiBuilder, true) + } else { + err = vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "PUT", map[string]string{ + "poolId": fmt.Sprint(vssConnection.PoolID), + "agentId": fmt.Sprint(taskAgent.ID), + }, map[string]string{}, taskAgent, taskAgent) + } if err != nil { - return nil, fmt.Errorf("failed to update taskAgent: %v\n", err.Error()) + return nil, fmt.Errorf("failed to update taskAgent: %v", err.Error()) } } } @@ -206,6 +243,46 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey return settings, nil } +type RSAKeyValue struct { + Modulus string + Exponent string +} + +func registerOrReplaceRunnerV2(taskAgent *protocol.TaskAgent, config *ConfigureRunner, vssConnection *protocol.VssConnection, apiBuilder *GithubApiUrlBuilder, replace bool) error { + runnerResp := &protocol.Runner{} + pubKeyXml, err := xml.Marshal(&RSAKeyValue{ + Modulus: taskAgent.Authorization.PublicKey.Modulus, + Exponent: taskAgent.Authorization.PublicKey.Exponent, + }) + if err != nil { + return err + } + v2Register := map[string]interface{}{ + "url": config.URL, + "group_id": vssConnection.PoolID, + "name": config.Name, + "version": taskAgent.Version, + "updates_disabled": taskAgent.DisableUpdate, + "ephemeral": taskAgent.Ephemeral, + "labels": taskAgent.Labels, + "public_key": string(pubKeyXml), + } + if replace { + v2Register["runner_id"] = taskAgent.ID + v2Register["replace"] = true + } + err = vssConnection.RequestWithContext2(context.Background(), "POST", apiBuilder.AbsoluteApiUrl("actions/runners/register"), "", v2Register, runnerResp) + if err != nil { + return err + } + taskAgent.ID = runnerResp.Id + taskAgent.Name = runnerResp.Name + taskAgent.Authorization.AuthorizationURL = runnerResp.Authorization.AuthorizationURL + taskAgent.Authorization.ClientID = runnerResp.Authorization.ClientId + taskAgent.ServerV2URL = runnerResp.Authorization.ServerURL + return nil +} + func (config *ConfigureRunner) ReadFromEnvironment() { config.ConfigureRemoveRunner.ReadFromEnvironment() if !config.Ephemeral { diff --git a/runnerconfiguration/common.go b/runnerconfiguration/common.go index 3860f38..f6a3a26 100644 --- a/runnerconfiguration/common.go +++ b/runnerconfiguration/common.go @@ -72,7 +72,7 @@ type RunnerInstance struct { WorkFolder string // Currently unused for actions/runner compat } -func (instance *RunnerInstance) EnshurePKey() error { +func (instance *RunnerInstance) EnsurePKey() error { if instance.PKey == nil { key, err := base64.StdEncoding.DecodeString(instance.Key) if err != nil { diff --git a/runnerconfiguration/compat/actions_runner_compat.go b/runnerconfiguration/compat/actions_runner_compat.go index f380870..723f606 100644 --- a/runnerconfiguration/compat/actions_runner_compat.go +++ b/runnerconfiguration/compat/actions_runner_compat.go @@ -4,7 +4,6 @@ import ( "crypto/rsa" "encoding/base64" "encoding/json" - "encoding/xml" "fmt" "math/big" "strconv" @@ -26,15 +25,17 @@ type DotnetRsaParameters struct { } type DotnetAgent struct { - AgentId string `json:"AgentId"` + AgentID string `json:"AgentId"` AgentName string `json:"AgentName"` DisableUpdate string `json:"DisableUpdate"` Ephemeral string `json:"Ephemeral"` - PoolId string `json:"PoolId"` + PoolID string `json:"PoolId"` PoolName string `json:"PoolName,omitempty"` - ServerUrl string `json:"ServerUrl"` + ServerURL string `json:"ServerUrl"` WorkFolder string `json:"WorkFolder"` - GitHubUrl string `json:"GitHubUrl"` + GitHubURL string `json:"GitHubUrl"` + UseV2Flow bool `json:"UseV2Flow"` + ServerURLV2 string `json:"ServerUrlV2"` } type DotnetCredentials struct { @@ -127,11 +128,11 @@ func ToRunnerInstance(fileAccess ConfigFileAccess) (*runnerconfiguration.RunnerI if err := fileAccess.Read(".credentials_rsaparams", rsaParameters); err != nil { return nil, err } - poolID, err := strconv.ParseInt(agent.PoolId, 10, 64) + poolID, err := strconv.ParseInt(agent.PoolID, 10, 64) if err != nil { return nil, err } - agentID, err := strconv.ParseInt(agent.AgentId, 10, 32) + agentID, err := strconv.ParseInt(agent.AgentID, 10, 64) if err != nil { return nil, err } @@ -140,11 +141,11 @@ func ToRunnerInstance(fileAccess ConfigFileAccess) (*runnerconfiguration.RunnerI return &runnerconfiguration.RunnerInstance{ PoolID: poolID, Auth: &protocol.GitHubAuthResult{ - TenantURL: agent.ServerUrl, + TenantURL: agent.ServerURL, }, PKey: FromRsaParameters(rsaParameters), Agent: &protocol.TaskAgent{ - ID: int(agentID), + ID: agentID, Ephemeral: ephemeral, Name: agent.AgentName, MaxParallelism: 1, @@ -154,22 +155,25 @@ func ToRunnerInstance(fileAccess ConfigFileAccess) (*runnerconfiguration.RunnerI }, DisableUpdate: disableUpdate, Version: "3.0.0", + ServerV2URL: agent.ServerURLV2, }, WorkFolder: agent.WorkFolder, - RegistrationURL: agent.GitHubUrl, + RegistrationURL: agent.GitHubURL, }, nil } func FromRunnerInstance(instance *runnerconfiguration.RunnerInstance, fileAccess ConfigFileAccess) error { agent := &DotnetAgent{ - AgentId: fmt.Sprint(instance.Agent.ID), + AgentID: fmt.Sprint(instance.Agent.ID), AgentName: instance.Agent.Name, Ephemeral: fmt.Sprint(instance.Agent.Ephemeral), DisableUpdate: fmt.Sprint(instance.Agent.DisableUpdate), - PoolId: fmt.Sprint(instance.PoolID), - ServerUrl: instance.Auth.TenantURL, + PoolID: fmt.Sprint(instance.PoolID), + ServerURL: instance.Auth.TenantURL, WorkFolder: instance.WorkFolder, - GitHubUrl: instance.RegistrationURL, + GitHubURL: instance.RegistrationURL, + UseV2Flow: instance.Auth.UseV2FLow, + ServerURLV2: instance.Agent.ServerV2URL, } if agent.WorkFolder == "" { agent.WorkFolder = "_work" @@ -187,7 +191,7 @@ func FromRunnerInstance(instance *runnerconfiguration.RunnerInstance, fileAccess if err := fileAccess.Write(".credentials", credentials); err != nil { return err } - if err := instance.EnshurePKey(); err != nil { + if err := instance.EnsurePKey(); err != nil { return err } if err := fileAccess.Write(".credentials_rsaparams", ToRsaParameters(instance.PKey)); err != nil { @@ -206,7 +210,6 @@ func ParseJitRunnerConfig(conf string) (*runnerconfiguration.RunnerSettings, err return nil, err } ret, err := ToRunnerInstance(JITConfigFileAccess(files)) - ToXmlString(&ret.PKey.PublicKey) return &runnerconfiguration.RunnerSettings{ Instances: []*runnerconfiguration.RunnerInstance{ ret, @@ -225,16 +228,3 @@ func ToJitRunnerConfig(instance *runnerconfiguration.RunnerInstance) (string, er } return base64.StdEncoding.EncodeToString(rawfiles), nil } - -type RSAKeyValue struct { - Modulus string - Exponent string -} - -func ToXmlString(publicKey *rsa.PublicKey) (string, error) { - res, err := xml.Marshal(&RSAKeyValue{ - Modulus: base64.StdEncoding.EncodeToString(publicKey.N.Bytes()), - Exponent: base64.StdEncoding.EncodeToString(big.NewInt(int64(publicKey.E)).Bytes()), - }) - return string(res), err -} diff --git a/runnerconfiguration/remove.go b/runnerconfiguration/remove.go index aafa841..1502d42 100644 --- a/runnerconfiguration/remove.go +++ b/runnerconfiguration/remove.go @@ -1,6 +1,7 @@ package runnerconfiguration import ( + "context" "fmt" "github.com/ChristopherHX/github-act-runner/protocol" @@ -73,16 +74,39 @@ func (config *RemoveRunner) Remove(settings *RunnerSettings, survey Survey, auth res = authres } - vssConnection := &protocol.VssConnection{ - Client: c, - TenantURL: res.TenantURL, - Token: res.Token, - PoolID: instance.PoolID, - Trace: config.Trace, - } - if err := vssConnection.DeleteAgent(instance.Agent); err != nil { - return fmt.Errorf("failed to remove Runner from server: %v\n", err) + if res.UseV2FLow { + // This is not based on any code of actions/runner + // it uses the pipelines api to remove the runner + vssConnection := &protocol.VssConnection{ + AuthHeader: "RemoteAuth " + config.Token, + Trace: config.Trace, + Client: c, + } + apiBuilder, err := NewGithubApiUrlBuilder(config.URL) + if err != nil { + return fmt.Errorf("invalid Url: %v", config.URL) + } + runnerURL, err := apiBuilder.ScopedApiUrl(fmt.Sprintf("actions/runners/%d", instance.Agent.ID)) + if err != nil { + return fmt.Errorf("failed to remove Runner from server: %v", err) + } + err = vssConnection.RequestWithContext2(context.Background(), "DELETE", runnerURL, "", nil, nil) + if err != nil { + return fmt.Errorf("failed to remove Runner from server: %v", err) + } + } else { + vssConnection := &protocol.VssConnection{ + Client: c, + TenantURL: res.TenantURL, + Token: res.Token, + PoolID: instance.PoolID, + Trace: config.Trace, + } + if err := vssConnection.DeleteAgent(instance.Agent); err != nil { + return fmt.Errorf("failed to remove Runner from server: %v", err) + } } + return nil }() if result != nil && !config.Force { From 1ea7dda8348cbbea4f4fad6b368fc1fcb94348f2 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 9 Mar 2025 12:40:27 +0100 Subject: [PATCH 3/8] add code for broker message listener --- actionsrunner/runner.go | 19 +++--------- protocol/connection.go | 37 ++++++++++++----------- protocol/session.go | 67 ++++++++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 49 deletions(-) diff --git a/actionsrunner/runner.go b/actionsrunner/runner.go index f8e8f61..3333fa0 100644 --- a/actionsrunner/runner.go +++ b/actionsrunner/runner.go @@ -281,14 +281,8 @@ func (run *RunRunner) Run(runnerenv RunnerEnvironment, listenerctx context.Conte } } session.Status = "Online" - err := vssConnection.RequestWithContext(xctx, "c3a054f6-7a8a-49c0-944e-3a8e5d7adfd7", "5.1-preview", "GET", map[string]string{ - "poolId": fmt.Sprint(instance.PoolID), - }, map[string]string{ - "sessionId": session.TaskAgentSession.SessionID, - "runnerVersion": "3.0.0", - "status": session.Status, - }, nil, message) - //TODO lastMessageId= + var err error + message, err = session.GetSingleMessage(xctx) if err != nil { if errors.Is(err, context.Canceled) { return 0 @@ -321,12 +315,7 @@ func (run *RunRunner) Run(runnerenv RunnerEnvironment, listenerctx context.Conte return 1 } success = true - err := vssConnection.Request("c3a054f6-7a8a-49c0-944e-3a8e5d7adfd7", "5.1-preview", "DELETE", map[string]string{ - "poolId": fmt.Sprint(instance.PoolID), - "messageId": fmt.Sprint(message.MessageID), - }, map[string]string{ - "sessionId": session.TaskAgentSession.SessionID, - }, nil, nil) + err := session.DeleteMessage(context.Background(), message) if err != nil { runnerenv.Printf("Failed to delete Message\n") success = false @@ -425,7 +414,7 @@ func runJob(runnerenv RunnerEnvironment, joblock *sync.Mutex, vssConnection *pro cancelJob() finishJob() }() - src, err := message.Decrypt(session.Block) + src, err := message.Decrypt(session) if err != nil { plogger.Printf("Failed to decode TaskAgentMessage: %v\n", err) return diff --git a/protocol/connection.go b/protocol/connection.go index 6d8dc81..6754155 100644 --- a/protocol/connection.go +++ b/protocol/connection.go @@ -294,36 +294,39 @@ func (vssConnection *VssConnection) GetAgentPools() (*TaskAgentPools, error) { } return _taskAgentPools, nil } -func (vssConnection *VssConnection) CreateSession(ctx context.Context) (*AgentMessageConnection, error) { + +func (vssConnection *VssConnection) CreateSessionExt(ctx context.Context, serverV2URL string) (*AgentMessageConnection, error) { session := &TaskAgentSession{} session.Agent = *vssConnection.TaskAgent session.UseFipsEncryption = false // Have to be set to false for "GitHub Enterprise Server 3.0.11", github.com reset it to false 24-07-2021 session.OwnerName = "RUNNER" - if err := vssConnection.RequestWithContext(ctx, "134e239e-2df3-4794-a6f6-24f1f19ec8dc", "5.1-preview", "POST", map[string]string{ - "poolId": fmt.Sprint(vssConnection.PoolID), - }, map[string]string{}, session, session); err != nil { - return nil, err + if serverV2URL != "" { + err := vssConnection.RequestWithContext2(ctx, "POST", serverV2URL+"/session", "", session, session) + if err != nil { + return nil, err + } + } else { + if err := vssConnection.RequestWithContext(ctx, "134e239e-2df3-4794-a6f6-24f1f19ec8dc", "5.1-preview", "POST", map[string]string{ + "poolId": fmt.Sprint(vssConnection.PoolID), + }, map[string]string{}, session, session); err != nil { + return nil, err + } + if session.BrokerMigrationMessage != nil { + return vssConnection.CreateSessionExt(ctx, session.BrokerMigrationMessage.BrokerBaseUrl) + } } con := &AgentMessageConnection{VssConnection: vssConnection, TaskAgentSession: session} - var err error - con.Block, err = con.TaskAgentSession.GetSessionKey(vssConnection.Key) - if err != nil { - _ = con.Delete(ctx) - return nil, err - } con.Status = "Online" return con, nil } +func (vssConnection *VssConnection) CreateSession(ctx context.Context) (*AgentMessageConnection, error) { + return vssConnection.CreateSessionExt(ctx, vssConnection.TaskAgent.ServerV2URL) +} + func (vssConnection *VssConnection) LoadSession(ctx context.Context, session *TaskAgentSession) (*AgentMessageConnection, error) { con := &AgentMessageConnection{VssConnection: vssConnection, TaskAgentSession: session} - var err error - con.Block, err = con.TaskAgentSession.GetSessionKey(vssConnection.Key) - if err != nil { - _ = con.Delete(ctx) - return nil, err - } con.Status = "Online" return con, nil } diff --git a/protocol/session.go b/protocol/session.go index 3f5aef1..3ac08d8 100644 --- a/protocol/session.go +++ b/protocol/session.go @@ -6,6 +6,7 @@ import ( "crypto/cipher" "crypto/rand" "crypto/rsa" + "net/url" "strings" // nolint:gosec @@ -27,7 +28,7 @@ type TaskAgentMessage struct { Body string } -func (message *TaskAgentMessage) Decrypt(block cipher.Block) ([]byte, error) { +func (message *TaskAgentMessage) Decrypt(session *AgentMessageConnection) ([]byte, error) { if message.IV == "" { return []byte(message.Body), nil } @@ -39,9 +40,17 @@ func (message *TaskAgentMessage) Decrypt(block cipher.Block) ([]byte, error) { if err != nil { return nil, err } - cbcdec := cipher.NewCBCDecrypter(block, iv) + if session.Block == nil { + // Parse Key + var err error + session.Block, err = session.TaskAgentSession.GetSessionKey(session.VssConnection.Key) + if err != nil { + return nil, err + } + } + cbcdec := cipher.NewCBCDecrypter(session.Block, iv) cbcdec.CryptBlocks(src, src) - maxlen := block.BlockSize() + maxlen := session.Block.BlockSize() validlen := len(src) if int(src[len(src)-1]) <= maxlen { // <= is needed if the message ends within a block boundary and maxlen=16 then we get 16 times char 16 appended, one whole extra block ok := true @@ -71,7 +80,7 @@ func (message *TaskAgentMessage) FetchBrokerIfNeeded(xctx context.Context, sessi if strings.EqualFold(message.MessageType, "BrokerMigration") { vssConnection := session.VssConnection rjrr := &BrokerMigration{} - raw, err := message.Decrypt(session.Block) + raw, err := message.Decrypt(session) if err != nil { return err } @@ -112,11 +121,12 @@ type TaskAgentSessionKey struct { } type TaskAgentSession struct { - SessionID string `json:",omitempty"` - EncryptionKey TaskAgentSessionKey - OwnerName string - Agent TaskAgent - UseFipsEncryption bool + SessionID string `json:",omitempty"` + EncryptionKey TaskAgentSessionKey + OwnerName string + Agent TaskAgent + UseFipsEncryption bool + BrokerMigrationMessage *BrokerMigration `json:",omitempty"` } func (session *TaskAgentSession) GetSessionKey(key *rsa.PrivateKey) (cipher.Block, error) { @@ -145,30 +155,49 @@ type AgentMessageConnection struct { TaskAgentSession *TaskAgentSession Block cipher.Block Status string + ServerV2URL string } func (session *AgentMessageConnection) Delete(ctx context.Context) error { + if session.ServerV2URL != "" { + return session.VssConnection.RequestWithContext2(ctx, "DELETE", session.ServerV2URL+"/session", "", nil, nil) + } return session.VssConnection.RequestWithContext(ctx, "134e239e-2df3-4794-a6f6-24f1f19ec8dc", "5.1-preview", "DELETE", map[string]string{ "poolId": fmt.Sprint(session.VssConnection.PoolID), "sessionId": session.TaskAgentSession.SessionID, }, map[string]string{}, session.TaskAgentSession, nil) } -func (session *AgentMessageConnection) GetNextMessage(ctx context.Context) (*TaskAgentMessage, error) { +func (session *AgentMessageConnection) GetSingleMessage(ctx context.Context) (*TaskAgentMessage, error) { message := &TaskAgentMessage{} - for { - select { - case <-ctx.Done(): - return nil, context.Canceled - default: - } - err := session.VssConnection.RequestWithContext(ctx, "c3a054f6-7a8a-49c0-944e-3a8e5d7adfd7", "5.1-preview", "GET", map[string]string{ + var err error + if session.ServerV2URL != "" { + query := url.Values{} + query.Set("sessionId", session.TaskAgentSession.SessionID) + query.Set("runnerVersion", "3.0.0") + query.Set("status", session.Status) + query.Set("disableUpdate", fmt.Sprint(session.TaskAgentSession.Agent.DisableUpdate)) + err = session.VssConnection.RequestWithContext2(ctx, "GET", session.ServerV2URL+"/message?"+query.Encode(), "", nil, message) + } else { + err = session.VssConnection.RequestWithContext(ctx, "c3a054f6-7a8a-49c0-944e-3a8e5d7adfd7", "5.1-preview", "GET", map[string]string{ "poolId": fmt.Sprint(session.VssConnection.PoolID), }, map[string]string{ "sessionId": session.TaskAgentSession.SessionID, "runnerVersion": "3.0.0", }, nil, message) // TODO lastMessageId= + } + return message, err +} + +func (session *AgentMessageConnection) GetNextMessage(ctx context.Context) (*TaskAgentMessage, error) { + for { + select { + case <-ctx.Done(): + return nil, context.Canceled + default: + } + message, err := session.GetSingleMessage(ctx) if err == nil { err = session.DeleteMessage(ctx, message) err = errors.Join(err, message.FetchBrokerIfNeeded(ctx, session)) @@ -191,6 +220,10 @@ func (session *AgentMessageConnection) GetNextMessage(ctx context.Context) (*Tas } func (session *AgentMessageConnection) DeleteMessage(ctx context.Context, message *TaskAgentMessage) error { + if session.ServerV2URL == "" { + // V2 no support for deleting messages + return nil + } return session.VssConnection.RequestWithContext(ctx, "c3a054f6-7a8a-49c0-944e-3a8e5d7adfd7", "5.1-preview", "DELETE", map[string]string{ "poolId": fmt.Sprint(session.VssConnection.PoolID), "messageId": fmt.Sprint(message.MessageID), From 1881e1aeadb996b6566c5ef88b3465660a0dec11 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 9 Mar 2025 12:45:10 +0100 Subject: [PATCH 4/8] fixup --- runnerconfiguration/add.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/runnerconfiguration/add.go b/runnerconfiguration/add.go index b08f542..681ad22 100644 --- a/runnerconfiguration/add.go +++ b/runnerconfiguration/add.go @@ -96,6 +96,17 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey return nil, err } poolList := &protocol.TaskAgentPools{} + poolList.Count = int64(len(runnerGroups.RunnerGroups)) + for _, val := range runnerGroups.RunnerGroups { + poolList.Value = append(poolList.Value, protocol.TaskAgentPool{ + TaskAgentPoolReference: protocol.TaskAgentPoolReference{ + ID: int64(val.Id), + Name: val.Name, + IsHosted: val.IsHosted, + IsInternal: val.IsDefault, + }, + }) + } return poolList, nil } } From 2ee24176159b09e37071ddfa07067bdac5c4e54b Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 9 Mar 2025 12:58:22 +0100 Subject: [PATCH 5/8] fixup --- runnerconfiguration/add.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runnerconfiguration/add.go b/runnerconfiguration/add.go index 681ad22..7da7c75 100644 --- a/runnerconfiguration/add.go +++ b/runnerconfiguration/add.go @@ -190,7 +190,7 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey taskAgent.DisableUpdate = config.DisableUpdate { var err error - if auth.UseV2FLow { + if res.UseV2FLow { err = registerOrReplaceRunnerV2(taskAgent, config, vssConnection, apiBuilder, false) } else { err = vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "POST", map[string]string{ @@ -203,7 +203,7 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey } // Try replaceing runner if creation failed taskAgents := &protocol.TaskAgents{} - if auth.UseV2FLow { + if res.UseV2FLow { resv2 := &protocol.ListRunnersResponse{} runnersURL, _ := apiBuilder.ScopedApiUrl("actions/runners") err = vssConnection.RequestWithContext2(context.Background(), "GET", runnersURL, "", nil, resv2) @@ -235,7 +235,7 @@ func (config *ConfigureRunner) Configure(settings *RunnerSettings, survey Survey if invalid { return nil, fmt.Errorf("failed to update taskAgent: Failed to find agent") } - if auth.UseV2FLow { + if res.UseV2FLow { err = registerOrReplaceRunnerV2(taskAgent, config, vssConnection, apiBuilder, true) } else { err = vssConnection.Request("e298ef32-5878-4cab-993c-043836571f42", "6.0-preview.2", "PUT", map[string]string{ From 1a102aa8575e4b7722f19763597da04e7c411536 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 9 Mar 2025 15:37:58 +0100 Subject: [PATCH 6/8] fix set missing status --- protocol/session.go | 1 + 1 file changed, 1 insertion(+) diff --git a/protocol/session.go b/protocol/session.go index 3ac08d8..64d88b9 100644 --- a/protocol/session.go +++ b/protocol/session.go @@ -184,6 +184,7 @@ func (session *AgentMessageConnection) GetSingleMessage(ctx context.Context) (*T }, map[string]string{ "sessionId": session.TaskAgentSession.SessionID, "runnerVersion": "3.0.0", + "status": session.Status, }, nil, message) // TODO lastMessageId= } From 0895bc6ae6cc07ed2ddc605e11e10ce654487d8c Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 9 Mar 2025 15:49:35 +0100 Subject: [PATCH 7/8] fix bug of deleting messages --- protocol/session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/session.go b/protocol/session.go index 64d88b9..2f2a78b 100644 --- a/protocol/session.go +++ b/protocol/session.go @@ -221,7 +221,7 @@ func (session *AgentMessageConnection) GetNextMessage(ctx context.Context) (*Tas } func (session *AgentMessageConnection) DeleteMessage(ctx context.Context, message *TaskAgentMessage) error { - if session.ServerV2URL == "" { + if session.ServerV2URL != "" { // V2 no support for deleting messages return nil } From 9ddb0e91d4d93dee6af712b234b60f86e5dd24f7 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Wed, 20 Aug 2025 19:46:48 +0000 Subject: [PATCH 8/8] fix lint --- protocol/connection.go | 2 +- protocol/runner_admin.go | 56 +++++++++++++++++------------------ protocol/session.go | 4 +-- runnerconfiguration/add.go | 7 +++-- runnerconfiguration/common.go | 39 ++++++++++++------------ runnerconfiguration/remove.go | 6 ++-- 6 files changed, 58 insertions(+), 56 deletions(-) diff --git a/protocol/connection.go b/protocol/connection.go index 3e03a5b..3f14755 100644 --- a/protocol/connection.go +++ b/protocol/connection.go @@ -350,7 +350,7 @@ func (vssConnection *VssConnection) CreateSessionExt(ctx context.Context, server return nil, err } if session.BrokerMigrationMessage != nil { - return vssConnection.CreateSessionExt(ctx, session.BrokerMigrationMessage.BrokerBaseUrl) + return vssConnection.CreateSessionExt(ctx, session.BrokerMigrationMessage.BrokerBaseURL) } } diff --git a/protocol/runner_admin.go b/protocol/runner_admin.go index 66e0c3b..7ddae88 100644 --- a/protocol/runner_admin.go +++ b/protocol/runner_admin.go @@ -1,28 +1,28 @@ -package protocol - -type Runner struct { - Name string `json:"name"` - Id int64 `json:"id"` - Authorization struct { - AuthorizationURL string `json:"authorization_url"` - ServerURL string `json:"server_url"` - ClientId string `json:"client_id"` - } `json:"authorization"` -} - -type RunnerGroup struct { - Id int32 `json:"id,omitempty"` - Name string `json:"name,omitempty"` - IsDefault bool `json:"default,omitempty"` - IsHosted bool `json:"is_hosted,omitempty"` -} - -type RunnerGroupList struct { - RunnerGroups []RunnerGroup `json:"runner_groups"` - Count int `json:"total_count"` -} - -type ListRunnersResponse struct { - TotalCount int `json:"total_count"` - Runners []Runner `json:"runners"` -} +package protocol + +type Runner struct { + Name string `json:"name"` + Id int64 `json:"id"` + Authorization struct { + AuthorizationURL string `json:"authorization_url"` + ServerURL string `json:"server_url"` + ClientId string `json:"client_id"` + } `json:"authorization"` +} + +type RunnerGroup struct { + Id int32 `json:"id,omitempty"` + Name string `json:"name,omitempty"` + IsDefault bool `json:"default,omitempty"` + IsHosted bool `json:"is_hosted,omitempty"` +} + +type RunnerGroupList struct { + RunnerGroups []RunnerGroup `json:"runner_groups"` + Count int `json:"total_count"` +} + +type ListRunnersResponse struct { + TotalCount int `json:"total_count"` + Runners []Runner `json:"runners"` +} diff --git a/protocol/session.go b/protocol/session.go index 9c9fe5d..1c538fb 100644 --- a/protocol/session.go +++ b/protocol/session.go @@ -6,9 +6,6 @@ import ( "crypto/cipher" "crypto/rand" "crypto/rsa" - "net/url" - "strings" - "crypto/sha1" "crypto/sha256" "encoding/base64" @@ -17,6 +14,7 @@ import ( "fmt" "hash" "io" + "net/url" "strings" "time" ) diff --git a/runnerconfiguration/add.go b/runnerconfiguration/add.go index 08be665..3558d5d 100644 --- a/runnerconfiguration/add.go +++ b/runnerconfiguration/add.go @@ -275,7 +275,9 @@ type RSAKeyValue struct { Exponent string } -func registerOrReplaceRunnerV2(taskAgent *protocol.TaskAgent, config *ConfigureRunner, vssConnection *protocol.VssConnection, apiBuilder *GithubApiUrlBuilder, replace bool) error { +func registerOrReplaceRunnerV2(taskAgent *protocol.TaskAgent, config *ConfigureRunner, + vssConnection *protocol.VssConnection, apiBuilder *GithubApiUrlBuilder, replace bool, +) error { runnerResp := &protocol.Runner{} pubKeyXml, err := xml.Marshal(&RSAKeyValue{ Modulus: taskAgent.Authorization.PublicKey.Modulus, @@ -298,7 +300,8 @@ func registerOrReplaceRunnerV2(taskAgent *protocol.TaskAgent, config *ConfigureR v2Register["runner_id"] = taskAgent.ID v2Register["replace"] = true } - err = vssConnection.RequestWithContext2(context.Background(), "POST", apiBuilder.AbsoluteApiUrl("actions/runners/register"), "", v2Register, runnerResp) + err = vssConnection.RequestWithContext2(context.Background(), "POST", + apiBuilder.AbsoluteApiUrl("actions/runners/register"), "", v2Register, runnerResp) if err != nil { return err } diff --git a/runnerconfiguration/common.go b/runnerconfiguration/common.go index 8bfb51b..2575103 100644 --- a/runnerconfiguration/common.go +++ b/runnerconfiguration/common.go @@ -106,8 +106,8 @@ type GithubApiUrlBuilder struct { ApiScope string } -func NewGithubApiUrlBuilder(URL string) (*GithubApiUrlBuilder, error) { - baseUrl, err := url.Parse(URL) +func NewGithubApiUrlBuilder(baseURLString string) (*GithubApiUrlBuilder, error) { + baseUrl, err := url.Parse(baseURLString) if err != nil { return nil, err } @@ -123,29 +123,30 @@ func NewGithubApiUrlBuilder(URL string) (*GithubApiUrlBuilder, error) { } func (apiBuilder *GithubApiUrlBuilder) AbsoluteApiUrl(p string) string { - url := *apiBuilder.URL - url.Path = path.Join(apiBuilder.ApiScope, p) - return url.String() + apiURL := *apiBuilder.URL + apiURL.Path = path.Join(apiBuilder.ApiScope, p) + return apiURL.String() } func (apiBuilder *GithubApiUrlBuilder) ScopedApiUrl(p string) (string, error) { - url := *apiBuilder.URL - paths := strings.Split(strings.TrimPrefix(url.Path, "/"), "/") + apiURL := *apiBuilder.URL + paths := strings.Split(strings.TrimPrefix(apiURL.Path, "/"), "/") if len(paths) == 1 { - url.Path = path.Join(apiBuilder.ApiScope, "orgs", paths[0], p) - } else if len(paths) == 2 { + apiURL.Path = path.Join(apiBuilder.ApiScope, "orgs", paths[0], p) + } else if len(paths) == repositoryPathSegments { scope := "repos" if strings.EqualFold(paths[0], "enterprises") { scope = "" } - url.Path = path.Join(apiBuilder.ApiScope, scope, paths[0], paths[1], p) + apiURL.Path = path.Join(apiBuilder.ApiScope, scope, paths[0], paths[1], p) } else { return "", fmt.Errorf("unsupported registration url") } - return url.String(), nil + return apiURL.String(), nil } -func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent string, apiEndpoint string, survey Survey) (*protocol.GitHubAuthResult, error) { +func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent, apiEndpoint string, survey Survey, +) (*protocol.GitHubAuthResult, error) { if config.URL == "" && !config.Unattended { config.URL = survey.GetInput("Which GitHub Url is associated with this runner (Normally this isn't missing):", "") } @@ -153,11 +154,11 @@ func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent strin if err != nil { return nil, fmt.Errorf("invalid Url: %v", config.URL) } - if len(config.Token) == 0 { - if len(config.Pat) > 0 { - url, err := apiBuilder.ScopedApiUrl(path.Join("actions/runners", apiEndpoint)) - if err != nil { - return nil, err + if config.Token == "" { + if config.Pat != "" { + apiURL, serr := apiBuilder.ScopedApiUrl(path.Join("actions/runners", apiEndpoint)) + if serr != nil { + return nil, serr } client := &protocol.VssConnection{ AuthHeader: fmt.Sprintf("Basic %v", base64.StdEncoding.EncodeToString([]byte("GitHub:"+config.Pat))), @@ -165,7 +166,7 @@ func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent strin Client: c, } tokenresp := &protocol.GitHubRunnerRegisterToken{} - err = client.RequestWithContext2(context.Background(), "POST", url, "", nil, tokenresp) + err = client.RequestWithContext2(context.Background(), "POST", apiURL, "", nil, tokenresp) if err != nil { return nil, fmt.Errorf("failed to retrieve %v token via pat: %v", apiEndpoint, err.Error()) } @@ -178,7 +179,7 @@ func gitHubAuth(config *ConfigureRemoveRunner, c *http.Client, runnerEvent strin return nil, fmt.Errorf("no runner registration token provided") } - finalregisterUrl := apiBuilder.AbsoluteApiUrl("actions/runner-registration") + finalregisterURL := apiBuilder.AbsoluteApiUrl("actions/runner-registration") client := &protocol.VssConnection{ AuthHeader: "RemoteAuth " + config.Token, diff --git a/runnerconfiguration/remove.go b/runnerconfiguration/remove.go index 7d7eb6c..96afa30 100644 --- a/runnerconfiguration/remove.go +++ b/runnerconfiguration/remove.go @@ -90,11 +90,11 @@ func (config *RemoveRunner) Remove(settings *RunnerSettings, survey Survey, auth } runnerURL, err := apiBuilder.ScopedApiUrl(fmt.Sprintf("actions/runners/%d", instance.Agent.ID)) if err != nil { - return fmt.Errorf("failed to remove Runner from server: %v", err) + return fmt.Errorf("failed to remove Runner from server: %w", err) } err = vssConnection.RequestWithContext2(context.Background(), "DELETE", runnerURL, "", nil, nil) if err != nil { - return fmt.Errorf("failed to remove Runner from server: %v", err) + return fmt.Errorf("failed to remove Runner from server: %w", err) } } else { vssConnection := &protocol.VssConnection{ @@ -105,7 +105,7 @@ func (config *RemoveRunner) Remove(settings *RunnerSettings, survey Survey, auth Trace: config.Trace, } if err := vssConnection.DeleteAgent(instance.Agent); err != nil { - return fmt.Errorf("failed to remove Runner from server: %v", err) + return fmt.Errorf("failed to remove Runner from server: %w", err) } }