mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00:00 
			
		
		
		
	Properly enforce gitea environment for pushes (#9501)
#8982 attempted to enforce the gitea environment for pushes - unfortunately it tested the settings before they were actually read in - and therefore does not do that!
This commit is contained in:
		
							
								
								
									
										16
									
								
								cmd/hook.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								cmd/hook.go
									
									
									
									
									
								
							| @@ -59,6 +59,12 @@ var ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func runHookPreReceive(c *cli.Context) error { | func runHookPreReceive(c *cli.Context) error { | ||||||
|  | 	if os.Getenv(models.EnvIsInternal) == "true" { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setup("hooks/pre-receive.log", false) | ||||||
|  |  | ||||||
| 	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | 	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | ||||||
| 		if setting.OnlyAllowPushIfGiteaEnvironmentSet { | 		if setting.OnlyAllowPushIfGiteaEnvironmentSet { | ||||||
| 			fail(`Rejecting changes as Gitea environment not set. | 			fail(`Rejecting changes as Gitea environment not set. | ||||||
| @@ -69,8 +75,6 @@ Gitea or set your environment appropriately.`, "") | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	setup("hooks/pre-receive.log", false) |  | ||||||
|  |  | ||||||
| 	// the environment setted on serv command | 	// the environment setted on serv command | ||||||
| 	isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | 	isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | ||||||
| 	username := os.Getenv(models.EnvRepoUsername) | 	username := os.Getenv(models.EnvRepoUsername) | ||||||
| @@ -186,6 +190,12 @@ func runHookUpdate(c *cli.Context) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func runHookPostReceive(c *cli.Context) error { | func runHookPostReceive(c *cli.Context) error { | ||||||
|  | 	if os.Getenv(models.EnvIsInternal) == "true" { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setup("hooks/post-receive.log", false) | ||||||
|  |  | ||||||
| 	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | 	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | ||||||
| 		if setting.OnlyAllowPushIfGiteaEnvironmentSet { | 		if setting.OnlyAllowPushIfGiteaEnvironmentSet { | ||||||
| 			fail(`Rejecting changes as Gitea environment not set. | 			fail(`Rejecting changes as Gitea environment not set. | ||||||
| @@ -196,8 +206,6 @@ Gitea or set your environment appropriately.`, "") | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	setup("hooks/post-receive.log", false) |  | ||||||
|  |  | ||||||
| 	// the environment setted on serv command | 	// the environment setted on serv command | ||||||
| 	repoUser := os.Getenv(models.EnvRepoUsername) | 	repoUser := os.Getenv(models.EnvRepoUsername) | ||||||
| 	isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | 	isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | ||||||
|   | |||||||
| @@ -10,6 +10,16 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // InternalPushingEnvironment returns an os environment to switch off hooks on push | ||||||
|  | // It is recommended to avoid using this unless you are pushing within a transaction | ||||||
|  | // or if you absolutely are sure that post-receive and pre-receive will do nothing | ||||||
|  | // We provide the full pushing-environment for other hook providers | ||||||
|  | func InternalPushingEnvironment(doer *User, repo *Repository) []string { | ||||||
|  | 	return append(PushingEnvironment(doer, repo), | ||||||
|  | 		EnvIsInternal+"=true", | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
| // PushingEnvironment returns an os environment to allow hooks to work on push | // PushingEnvironment returns an os environment to allow hooks to work on push | ||||||
| func PushingEnvironment(doer *User, repo *Repository) []string { | func PushingEnvironment(doer *User, repo *Repository) []string { | ||||||
| 	return FullPushingEnvironment(doer, doer, repo, repo.Name, 0) | 	return FullPushingEnvironment(doer, doer, repo, repo.Name, 0) | ||||||
|   | |||||||
| @@ -1012,7 +1012,7 @@ func createDelegateHooks(repoPath string) (err error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // initRepoCommit temporarily changes with work directory. | // initRepoCommit temporarily changes with work directory. | ||||||
| func initRepoCommit(tmpPath string, u *User) (err error) { | func initRepoCommit(tmpPath string, repo *Repository, u *User) (err error) { | ||||||
| 	commitTimeStr := time.Now().Format(time.RFC3339) | 	commitTimeStr := time.Now().Format(time.RFC3339) | ||||||
|  |  | ||||||
| 	sig := u.NewGitSig() | 	sig := u.NewGitSig() | ||||||
| @@ -1061,7 +1061,7 @@ func initRepoCommit(tmpPath string, u *User) (err error) { | |||||||
|  |  | ||||||
| 	if stdout, err := git.NewCommand("push", "origin", "master"). | 	if stdout, err := git.NewCommand("push", "origin", "master"). | ||||||
| 		SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). | 		SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). | ||||||
| 		RunInDir(tmpPath); err != nil { | 		RunInDirWithEnv(tmpPath, InternalPushingEnvironment(u, repo)); err != nil { | ||||||
| 		log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) | 		log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) | ||||||
| 		return fmt.Errorf("git push: %v", err) | 		return fmt.Errorf("git push: %v", err) | ||||||
| 	} | 	} | ||||||
| @@ -1219,7 +1219,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Apply changes and commit. | 		// Apply changes and commit. | ||||||
| 		if err = initRepoCommit(tmpDir, u); err != nil { | 		if err = initRepoCommit(tmpDir, repo, u); err != nil { | ||||||
| 			return fmt.Errorf("initRepoCommit: %v", err) | 			return fmt.Errorf("initRepoCommit: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -174,7 +174,7 @@ func generateRepoCommit(e Engine, repo, templateRepo, generateRepo *Repository, | |||||||
| 		return fmt.Errorf("git remote add: %v", err) | 		return fmt.Errorf("git remote add: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return initRepoCommit(tmpDir, repo.Owner) | 	return initRepoCommit(tmpDir, repo, repo.Owner) | ||||||
| } | } | ||||||
|  |  | ||||||
| // generateRepository initializes repository from template | // generateRepository initializes repository from template | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ const ( | |||||||
| 	EnvPusherID     = "GITEA_PUSHER_ID" | 	EnvPusherID     = "GITEA_PUSHER_ID" | ||||||
| 	EnvKeyID        = "GITEA_KEY_ID" | 	EnvKeyID        = "GITEA_KEY_ID" | ||||||
| 	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY" | 	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY" | ||||||
|  | 	EnvIsInternal   = "GITEA_INTERNAL_PUSH" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // CommitToPushCommit transforms a git.Commit to PushCommit type. | // CommitToPushCommit transforms a git.Commit to PushCommit type. | ||||||
|   | |||||||
| @@ -242,10 +242,19 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) { | |||||||
|  |  | ||||||
| 	_ = os.Remove(file) | 	_ = os.Remove(file) | ||||||
|  |  | ||||||
|  | 	if err = pr.LoadIssue(); err != nil { | ||||||
|  | 		return fmt.Errorf("unable to load issue %d for pr %d: %v", pr.IssueID, pr.ID, err) | ||||||
|  | 	} | ||||||
|  | 	if err = pr.Issue.LoadPoster(); err != nil { | ||||||
|  | 		return fmt.Errorf("unable to load poster %d for pr %d: %v", pr.Issue.PosterID, pr.ID, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if err = git.Push(headRepoPath, git.PushOptions{ | 	if err = git.Push(headRepoPath, git.PushOptions{ | ||||||
| 		Remote: tmpRemoteName, | 		Remote: tmpRemoteName, | ||||||
| 		Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile), | 		Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile), | ||||||
| 		Force:  true, | 		Force:  true, | ||||||
|  | 		// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/... | ||||||
|  | 		Env: models.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo), | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		return fmt.Errorf("Push: %v", err) | 		return fmt.Errorf("Push: %v", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user