diff --git a/apps/gitea-webhook-ambassador/configs/configs.example.yaml b/apps/gitea-webhook-ambassador/configs/configs.example.yaml index ee90fb58..55ff13e6 100644 --- a/apps/gitea-webhook-ambassador/configs/configs.example.yaml +++ b/apps/gitea-webhook-ambassador/configs/configs.example.yaml @@ -2,6 +2,7 @@ server: port: 8080 webhookPath: "/webhook" secretHeader: "X-Gitea-Signature" + secretKey: "custom-secret-key" jenkins: url: "http://jenkins.example.com" diff --git a/apps/gitea-webhook-ambassador/main.go b/apps/gitea-webhook-ambassador/main.go index 131e4b07..6bb4090a 100644 --- a/apps/gitea-webhook-ambassador/main.go +++ b/apps/gitea-webhook-ambassador/main.go @@ -1,10 +1,6 @@ package main import ( - "bytes" - "crypto/hmac" - "crypto/sha256" - "encoding/hex" "encoding/json" "flag" "fmt" @@ -29,7 +25,8 @@ type Configuration struct { Server struct { Port int `yaml:"port" validate:"required,gt=0"` WebhookPath string `yaml:"webhookPath" validate:"required"` - SecretHeader string `yaml:"secretHeader" default:"X-Gitea-Signature"` + SecretHeader string `yaml:"secretHeader" default:"Authorization"` + SecretKey string `yaml:"secretKey"` } `yaml:"server"` Jenkins struct { @@ -486,17 +483,19 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) { // Verify signature if secret token is set configMutex.RLock() - secretToken := config.Gitea.SecretToken secretHeader := config.Server.SecretHeader + serverSecretKey := config.Server.SecretKey configMutex.RUnlock() - if secretToken != "" { - signature := r.Header.Get(secretHeader) - if !verifySignature(r, signature, secretToken) { - http.Error(w, "Invalid signature", http.StatusUnauthorized) - logWarn("Invalid webhook signature received") - return - } + // If server secret key is set, use it as the secret token + receivedSecretKey := r.Header.Get(secretHeader) + if receivedSecretKey == "" { + http.Error(w, "Invalid server secret key", http.StatusUnauthorized) + logWarn("No secret key provided in header") + } else if receivedSecretKey != serverSecretKey { + http.Error(w, "Invalid server secret key", http.StatusUnauthorized) + logWarn("Invalid server secret key provided") + return } // Read and parse the webhook payload @@ -619,47 +618,34 @@ func determineJobName(config ProjectConfig, branchName string) string { return "" } -func verifySignature(r *http.Request, signature string, secret string) bool { - if signature == "" { - return false - } - - body, err := io.ReadAll(r.Body) - if err != nil { - return false - } - // Reset the body for subsequent reads - r.Body = io.NopCloser(bytes.NewBuffer(body)) - - // The signature from Gitea is in format "sha256=HASH" - parts := strings.SplitN(signature, "=", 2) - if len(parts) != 2 { - return false - } - - mac := hmac.New(sha256.New, []byte(secret)) - mac.Write(body) - expectedMAC := mac.Sum(nil) - receivedMAC, err := hex.DecodeString(parts[1]) - if err != nil { - return false - } - - return hmac.Equal(expectedMAC, receivedMAC) -} - func triggerJenkinsJob(job jobRequest) bool { configMutex.RLock() - jenkinsURL := fmt.Sprintf("%s/job/%s/buildWithParameters", - strings.TrimSuffix(config.Jenkins.URL, "/"), - job.jobName) + jenkinsBaseURL := strings.TrimSuffix(config.Jenkins.URL, "/") jenkinsUser := config.Jenkins.Username jenkinsToken := config.Jenkins.Token configMutex.RUnlock() + // Handle Jenkins job paths correctly + // Jenkins jobs can be organized in folders, with proper URL format: + // /job/folder1/job/folder2/job/jobname + jobPath := job.jobName + + // If job name contains slashes, format it properly for Jenkins URL + if strings.Contains(jobPath, "/") { + // Replace regular slashes with "/job/" for Jenkins URL format + parts := strings.Split(jobPath, "/") + jobPath = "job/" + strings.Join(parts, "/job/") + } else { + jobPath = "job/" + jobPath + } + + jenkinsURL := fmt.Sprintf("%s/%s/buildWithParameters", jenkinsBaseURL, jobPath) + + logDebug("Triggering Jenkins job URL: %s", jenkinsURL) + req, err := http.NewRequest("POST", jenkinsURL, nil) if err != nil { - logger.Printf("Error creating Jenkins request for job %s: %v", job.jobName, err) + logError("Error creating Jenkins request for job %s: %v", job.jobName, err) return false } @@ -678,19 +664,19 @@ func triggerJenkinsJob(job jobRequest) bool { // Execute request resp, err := httpClient.Do(req) if err != nil { - logger.Printf("Error triggering Jenkins job %s: %v", job.jobName, err) + logError("Error triggering Jenkins job %s: %v", job.jobName, err) return false } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { bodyBytes, _ := io.ReadAll(resp.Body) - logger.Printf("Jenkins returned error for job %s: status=%d, body=%s", - job.jobName, resp.StatusCode, string(bodyBytes)) + logError("Jenkins returned error for job %s: status=%d, URL=%s, body=%s", + job.jobName, resp.StatusCode, jenkinsURL, string(bodyBytes)) return false } - logger.Printf("Successfully triggered Jenkins job %s for event %s", + logInfo("Successfully triggered Jenkins job %s for event %s", job.jobName, job.eventID) return true } diff --git a/cluster/manifests/freeleaps-devops-system/gitea-webhook-ambassador/configmap.yaml b/cluster/manifests/freeleaps-devops-system/gitea-webhook-ambassador/configmap.yaml index 89daaf53..e90800da 100644 --- a/cluster/manifests/freeleaps-devops-system/gitea-webhook-ambassador/configmap.yaml +++ b/cluster/manifests/freeleaps-devops-system/gitea-webhook-ambassador/configmap.yaml @@ -10,10 +10,11 @@ data: server: port: 8080 webhookPath: "/webhook" - secretHeader: "X-Gitea-Signature" + secretHeader: "Authorization" + secretKey: "r6Y@QTb*7BQN@hDGsN" jenkins: - url: "http://jenkins.freeleaps-devops-system.svc.cluster.local:8080" + url: "http://jenkins.freeleaps-devops-system.svc.freeleaps.cluster:8080" username: "admin" token: "115127e693f1bc6b7194f58ff6d6283bd0" timeout: 30 diff --git a/freeleaps/alpha/ci/freeleaps-service-hub/Jenkinsfile b/freeleaps/alpha/ci/freeleaps-service-hub/Jenkinsfile index 8d6fcaab..4a9cb14d 100644 --- a/freeleaps/alpha/ci/freeleaps-service-hub/Jenkinsfile +++ b/freeleaps/alpha/ci/freeleaps-service-hub/Jenkinsfile @@ -3,10 +3,10 @@ library 'first-class-pipeline' executeFreeleapsPipeline { serviceName = 'freeleaps' environmentSlug = 'alpha' - serviceGitBranch = 'develop' - serviceGitRepo = "https://freeleaps@dev.azure.com/freeleaps/freeleaps-service-hub/_git/freeleaps-service-hub" + serviceGitBranch = 'dev' + serviceGitRepo = "https://gitea.freeleaps.mathmast.com/freeleaps/freeleaps-service-hub.git" serviceGitRepoType = 'monorepo' - serviceGitCredentialsId = 'freeleaps-azure-devops-credentials' + serviceGitCredentialsId = 'freeleaps-repos-gitea-credentails' executeMode = 'fully' commitMessageLintEnabled = false components = [ diff --git a/freeleaps/alpha/ci/freeleaps2-devsvc/Jenkinsfile b/freeleaps/alpha/ci/freeleaps2-devsvc/Jenkinsfile index d8458371..6ce4dd33 100644 --- a/freeleaps/alpha/ci/freeleaps2-devsvc/Jenkinsfile +++ b/freeleaps/alpha/ci/freeleaps2-devsvc/Jenkinsfile @@ -3,8 +3,8 @@ library 'first-class-pipeline' executeFreeleapsPipeline { serviceName = 'freeleaps' environmentSlug = 'alpha' - serviceGitBranch = 'develop' - serviceGitRepo = "https://freeleaps@dev.azure.com/freeleaps/freeleaps2-devsvc/_git/freeleaps2-devsvc" + serviceGitBranch = 'dev' + serviceGitRepo = "https://gitea.freeleaps.mathmast.com/freeleaps/freeleaps2-devsvc.git" serviceGitRepoType = 'monorepo' serviceGitCredentialsId = 'freeleaps-azure-devops-credentials' executeMode = 'fully' diff --git a/freeleaps/alpha/ci/freeleaps2-frontend/Jenkinsfile b/freeleaps/alpha/ci/freeleaps2-frontend/Jenkinsfile index 8f562349..31e1fa94 100644 --- a/freeleaps/alpha/ci/freeleaps2-frontend/Jenkinsfile +++ b/freeleaps/alpha/ci/freeleaps2-frontend/Jenkinsfile @@ -3,8 +3,8 @@ library 'first-class-pipeline' executeFreeleapsPipeline { serviceName = 'freeleaps' environmentSlug = 'alpha' - serviceGitBranch = 'develop' - serviceGitRepo = "https://freeleaps@dev.azure.com/freeleaps/freeleaps2-frontend/_git/freeleaps2-frontend" + serviceGitBranch = 'dev' + serviceGitRepo = "https://gitea.freeleaps.mathmast.com/products/freeleaps.git" serviceGitRepoType = 'monorepo' serviceGitCredentialsId = 'freeleaps-azure-devops-credentials' executeMode = 'fully'