mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 00:11:04 +00:00 
			
		
		
		
	To audit access to our forgejo-instance we currently need to enable debug ssh-logs. It turns out a single log become multiple events in a k8s/container setup. To have our log-collectors properly join these events, we would like to indent them similar to what some stacktraces look like.
This PR would change
```
2025/09/08 07:18:53 ...eb/routing/logger.go:102:func1() [I] Serv Results:
IsWiki: %t
DeployKeyID: %d
KeyID: %d    KeyName: %s
UserName: %s
UserID: %d
OwnerName: %s
RepoName: %s
RepoID: %d
```
to
```
2025/09/08 07:18:53 ...eb/routing/logger.go:102:func1() [I] Serv Results:
    IsWiki: %t
    DeployKeyID: %d
    KeyID: %d    KeyName: %s
    UserName: %s
    UserID: %d
    OwnerName: %s
    RepoName: %s
    RepoID: %d
```
Furthermore to standardize user configuration of ssh-logs I have added `LOGGER_SSH_MODE` . It can be configured like router-logger. By doing so we can change the log-LEVEL to debug for ssh without changing other loggers. This would deprecate `ENABLE_SSH_LOG`.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.
<!--start release-notes-assistant-->
## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9056): <!--number 9056 --><!--line 0 --><!--description ZmVhdChsb2cpOiBiZXR0ZXIgcGFyc2VhYmxlIGFuZCBjb25maWd1cmFibGUgc3NoLWxvZ3M=-->feat(log): better parseable and configurable ssh-logs<!--description-->
<!--end release-notes-assistant-->
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9056
Reviewed-by: Lucas <sclu1034@noreply.codeberg.org>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: zokki <zokki.softwareschmiede@gmail.com>
Co-committed-by: zokki <zokki.softwareschmiede@gmail.com>
		
	
			
		
			
				
	
	
		
			130 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package private
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"net/url"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"forgejo.org/modules/git"
 | 
						|
	"forgejo.org/modules/git/pushoptions"
 | 
						|
	"forgejo.org/modules/log"
 | 
						|
	"forgejo.org/modules/repository"
 | 
						|
	"forgejo.org/modules/setting"
 | 
						|
)
 | 
						|
 | 
						|
// Git environment variables
 | 
						|
const (
 | 
						|
	GitAlternativeObjectDirectories = "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 | 
						|
	GitObjectDirectory              = "GIT_OBJECT_DIRECTORY"
 | 
						|
	GitQuarantinePath               = "GIT_QUARANTINE_PATH"
 | 
						|
)
 | 
						|
 | 
						|
// HookOptions represents the options for the Hook calls
 | 
						|
type HookOptions struct {
 | 
						|
	OldCommitIDs                    []string
 | 
						|
	NewCommitIDs                    []string
 | 
						|
	RefFullNames                    []git.RefName
 | 
						|
	UserID                          int64
 | 
						|
	UserName                        string
 | 
						|
	GitObjectDirectory              string
 | 
						|
	GitAlternativeObjectDirectories string
 | 
						|
	GitQuarantinePath               string
 | 
						|
	GitPushOptions                  map[string]string
 | 
						|
	PullRequestID                   int64
 | 
						|
	PushTrigger                     repository.PushTrigger
 | 
						|
	DeployKeyID                     int64 // if the pusher is a DeployKey, then UserID is the repo's org user.
 | 
						|
	IsWiki                          bool
 | 
						|
	ActionPerm                      int
 | 
						|
}
 | 
						|
 | 
						|
func (o *HookOptions) GetGitPushOptions() pushoptions.Interface {
 | 
						|
	return pushoptions.NewFromMap(&o.GitPushOptions)
 | 
						|
}
 | 
						|
 | 
						|
// SSHLogOption ssh log options
 | 
						|
type SSHLogOption struct {
 | 
						|
	Level   log.Level
 | 
						|
	Message string
 | 
						|
}
 | 
						|
 | 
						|
// HookPostReceiveResult represents an individual result from PostReceive
 | 
						|
type HookPostReceiveResult struct {
 | 
						|
	Results      []HookPostReceiveBranchResult
 | 
						|
	RepoWasEmpty bool
 | 
						|
	Err          string
 | 
						|
}
 | 
						|
 | 
						|
// HookPostReceiveBranchResult represents an individual branch result from PostReceive
 | 
						|
type HookPostReceiveBranchResult struct {
 | 
						|
	Message bool
 | 
						|
	Create  bool
 | 
						|
	Branch  string
 | 
						|
	URL     string
 | 
						|
}
 | 
						|
 | 
						|
// HookProcReceiveResult represents an individual result from ProcReceive
 | 
						|
type HookProcReceiveResult struct {
 | 
						|
	Results []HookProcReceiveRefResult
 | 
						|
	Err     string
 | 
						|
}
 | 
						|
 | 
						|
// HookProcReceiveRefResult represents an individual result from ProcReceive
 | 
						|
type HookProcReceiveRefResult struct {
 | 
						|
	OldOID       string
 | 
						|
	NewOID       string
 | 
						|
	Ref          string
 | 
						|
	OriginalRef  git.RefName
 | 
						|
	IsForcePush  bool
 | 
						|
	IsNotMatched bool
 | 
						|
	Err          string
 | 
						|
}
 | 
						|
 | 
						|
// HookPreReceive check whether the provided commits are allowed
 | 
						|
func HookPreReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) ResponseExtra {
 | 
						|
	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
 | 
						|
	req := newInternalRequest(ctx, reqURL, "POST", opts)
 | 
						|
	req.SetReadWriteTimeout(time.Duration(60+len(opts.OldCommitIDs)) * time.Second)
 | 
						|
	_, extra := requestJSONResp(req, &ResponseText{})
 | 
						|
	return extra
 | 
						|
}
 | 
						|
 | 
						|
// HookPostReceive updates services and users
 | 
						|
func HookPostReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) (*HookPostReceiveResult, ResponseExtra) {
 | 
						|
	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/post-receive/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
 | 
						|
	req := newInternalRequest(ctx, reqURL, "POST", opts)
 | 
						|
	req.SetReadWriteTimeout(time.Duration(60+len(opts.OldCommitIDs)) * time.Second)
 | 
						|
	return requestJSONResp(req, &HookPostReceiveResult{})
 | 
						|
}
 | 
						|
 | 
						|
// HookProcReceive proc-receive hook
 | 
						|
func HookProcReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) (*HookProcReceiveResult, ResponseExtra) {
 | 
						|
	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/proc-receive/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
 | 
						|
 | 
						|
	req := newInternalRequest(ctx, reqURL, "POST", opts)
 | 
						|
	req.SetReadWriteTimeout(time.Duration(60+len(opts.OldCommitIDs)) * time.Second)
 | 
						|
	return requestJSONResp(req, &HookProcReceiveResult{})
 | 
						|
}
 | 
						|
 | 
						|
// SetDefaultBranch will set the default branch to the provided branch for the provided repository
 | 
						|
func SetDefaultBranch(ctx context.Context, ownerName, repoName, branch string) ResponseExtra {
 | 
						|
	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/set-default-branch/%s/%s/%s",
 | 
						|
		url.PathEscape(ownerName),
 | 
						|
		url.PathEscape(repoName),
 | 
						|
		url.PathEscape(branch),
 | 
						|
	)
 | 
						|
	req := newInternalRequest(ctx, reqURL, "POST")
 | 
						|
	_, extra := requestJSONResp(req, &ResponseText{})
 | 
						|
	return extra
 | 
						|
}
 | 
						|
 | 
						|
// SSHLog sends ssh error log response
 | 
						|
func SSHLog(ctx context.Context, level log.Level, msg string) error {
 | 
						|
	reqURL := setting.LocalURL + "api/internal/ssh/log"
 | 
						|
	req := newInternalRequest(ctx, reqURL, "POST", &SSHLogOption{Level: level, Message: msg})
 | 
						|
	_, extra := requestJSONResp(req, &ResponseText{})
 | 
						|
	return extra.Error
 | 
						|
}
 |