Skip to content

Add Audit Trail/Logging #24257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 86 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
afcb22b
Add audit event logging.
KN4CK3R Apr 17, 2023
204b114
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Apr 18, 2023
2dcff01
Added file logging.
KN4CK3R Apr 18, 2023
9d7b3c8
Fixes.
KN4CK3R Apr 21, 2023
6d7835a
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Apr 21, 2023
6e6305d
Added documentation.
KN4CK3R Apr 21, 2023
f36f208
Lint docs.
KN4CK3R Apr 21, 2023
8939539
Fixed typo.
KN4CK3R Apr 21, 2023
7131cf6
Remove errors.Join.
KN4CK3R Apr 21, 2023
f732ae6
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Apr 21, 2023
0f56aa1
Fix merge error.
KN4CK3R Apr 21, 2023
8038aee
Update models/db/context.go
KN4CK3R Apr 23, 2023
fb3f954
Change method name.
KN4CK3R Apr 23, 2023
b3779fc
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Apr 23, 2023
c7e989a
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Apr 24, 2023
659c324
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 7, 2023
3c613b3
Remove notice appender.
KN4CK3R May 7, 2023
11ddf58
Use errors.Join.
KN4CK3R May 7, 2023
033c8fe
lint
KN4CK3R May 7, 2023
777362e
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 16, 2023
3684f3a
Fix queue merge error.
KN4CK3R May 16, 2023
7e474a6
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 22, 2023
5615970
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 27, 2023
9e7082b
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Jun 12, 2023
3d1f881
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Jun 25, 2023
2c01fe2
Merge branch 'main' into feature-audit
KN4CK3R Jun 30, 2023
ab956ba
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Jul 9, 2023
073603f
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Aug 6, 2023
718f1a9
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Aug 14, 2023
f69976e
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Aug 30, 2023
65e4f7c
Add tests.
KN4CK3R Aug 31, 2023
d1b5a22
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Sep 5, 2023
59aa27f
Apply suggestions.
KN4CK3R Sep 5, 2023
1294a00
Merge tests.
KN4CK3R Sep 5, 2023
d2930ec
Apply suggestions from code review
KN4CK3R Sep 6, 2023
bf5f725
Fix format string.
KN4CK3R Sep 6, 2023
d1445eb
Change log message.
KN4CK3R Sep 6, 2023
6b0b2f7
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Sep 15, 2023
8d21f95
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Sep 16, 2023
1a28a97
Use new PushMirror.RemoteAddress.
KN4CK3R Sep 16, 2023
5d51639
Add some suggestions.
KN4CK3R Sep 22, 2023
001727e
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Sep 22, 2023
4c6eabe
Change sudo target.
KN4CK3R Sep 22, 2023
ec6ae2f
Remove ReleaseReopen.
KN4CK3R Sep 22, 2023
10fed1c
Remove todo.
KN4CK3R Sep 22, 2023
bbb0322
Use existing cron user.
KN4CK3R Sep 23, 2023
c95c03f
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Sep 23, 2023
d153e4d
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Oct 13, 2023
1fa5edd
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Nov 5, 2023
989fb36
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Nov 12, 2023
41287b9
Add ip address to audit log.
KN4CK3R Nov 12, 2023
c5ff607
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Nov 16, 2023
d56fae1
Simplify appender.
KN4CK3R Nov 16, 2023
20d6fdd
Add database logging.
KN4CK3R Nov 19, 2023
8c64051
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Nov 19, 2023
3b945d9
Display audit logs in admin/org/repo settings.
KN4CK3R Nov 21, 2023
e928e40
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Nov 21, 2023
af5b9b6
fix lint
KN4CK3R Nov 21, 2023
9885036
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Nov 26, 2023
fa8d530
lint
KN4CK3R Nov 26, 2023
95682a3
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Dec 28, 2023
ec55854
Add some suggestions.
KN4CK3R Dec 29, 2023
0de61c3
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Feb 6, 2024
6fffaac
Use individual methods.
KN4CK3R Feb 6, 2024
278ca4b
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Feb 7, 2024
3b1336a
Log system startup/shutdown.
KN4CK3R Feb 8, 2024
d090810
Add audit logs to user settings.
KN4CK3R Feb 8, 2024
558fd1a
Update docs.
KN4CK3R Feb 8, 2024
bcd6f99
Merge branch 'main' into feature-audit
delvh Feb 18, 2024
ac2b8f3
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Feb 24, 2024
745be63
Add suggestions.
KN4CK3R Feb 24, 2024
3b7298b
Merge branch 'main' into feature-audit
6543 Feb 25, 2024
cfebe22
Apply suggestions from code review
KN4CK3R Mar 1, 2024
b813aba
Fix migration.
KN4CK3R Mar 2, 2024
59f1537
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 2, 2024
4e41c8b
Use `ConfigSectionKeyBool`.
KN4CK3R Mar 2, 2024
c4d5fd2
Fix context imports.
KN4CK3R Mar 2, 2024
d6fd348
Fix imports.
KN4CK3R Mar 2, 2024
12dc51c
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 4, 2024
3a919d2
Fix typo.
KN4CK3R Mar 4, 2024
9482ee0
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Apr 21, 2024
7ae645e
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 14, 2024
a68292b
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Jun 25, 2024
00359c7
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Aug 7, 2024
694ba9b
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Aug 7, 2024
4644d76
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 23 additions & 26 deletions models/asymkey/ssh_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,17 +317,17 @@ func PublicKeyIsExternallyManaged(id int64) (bool, error) {
return false, nil
}

// deleteKeysMarkedForDeletion returns true if ssh keys needs update
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
// deleteKeysMarkedForDeletion returns the deleted keys
func deleteKeysMarkedForDeletion(keys []string) ([]*PublicKey, error) {
// Start session
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return false, err
return nil, err
}
defer committer.Close()

// Delete keys marked for deletion
var sshKeysNeedUpdate bool
deletedKeys := make([]*PublicKey, 0, len(keys))

for _, KeyToDelete := range keys {
key, err := SearchPublicKeyByContent(ctx, KeyToDelete)
if err != nil {
Expand All @@ -338,19 +338,21 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
log.Error("deletePublicKeys: %v", err)
continue
}
sshKeysNeedUpdate = true

deletedKeys = append(deletedKeys, key)
}

if err := committer.Commit(); err != nil {
return false, err
return nil, err
}

return sshKeysNeedUpdate, nil
return deletedKeys, nil
}

// AddPublicKeysBySource add a users public keys. Returns true if there are changes.
func AddPublicKeysBySource(usr *user_model.User, s *auth.Source, sshPublicKeys []string) bool {
var sshKeysNeedUpdate bool
// AddPublicKeysBySource add a users public keys. Returns the added keys.
func AddPublicKeysBySource(usr *user_model.User, s *auth.Source, sshPublicKeys []string) []*PublicKey {
addedKeys := make([]*PublicKey, 0, len(sshPublicKeys))

for _, sshKey := range sshPublicKeys {
var err error
found := false
Expand All @@ -368,28 +370,27 @@ func AddPublicKeysBySource(usr *user_model.User, s *auth.Source, sshPublicKeys [
marshalled = marshalled[:len(marshalled)-1]
sshKeyName := fmt.Sprintf("%s-%s", s.Name, ssh.FingerprintSHA256(out))

if _, err := AddPublicKey(usr.ID, sshKeyName, marshalled, s.ID); err != nil {
if pubKey, err := AddPublicKey(usr.ID, sshKeyName, marshalled, s.ID); err != nil {
if IsErrKeyAlreadyExist(err) {
log.Trace("AddPublicKeysBySource[%s]: Public SSH Key %s already exists for user", sshKeyName, usr.Name)
} else {
log.Error("AddPublicKeysBySource[%s]: Error adding Public SSH Key for user %s: %v", sshKeyName, usr.Name, err)
}
} else {
addedKeys = append(addedKeys, pubKey)

log.Trace("AddPublicKeysBySource[%s]: Added Public SSH Key for user %s", sshKeyName, usr.Name)
sshKeysNeedUpdate = true
}
}
if !found && err != nil {
log.Warn("AddPublicKeysBySource[%s]: Skipping invalid Public SSH Key for user %s: %v", s.Name, usr.Name, sshKey)
}
}
return sshKeysNeedUpdate
return addedKeys
}

// SynchronizePublicKeys updates a users public keys. Returns true if there are changes.
func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys []string) bool {
var sshKeysNeedUpdate bool

func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys []string) ([]*PublicKey, []*PublicKey) {
log.Trace("synchronizePublicKeys[%s]: Handling Public SSH Key synchronization for user %s", s.Name, usr.Name)

// Get Public Keys from DB with current LDAP source
Expand Down Expand Up @@ -418,7 +419,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
// Check if Public Key sync is needed
if util.SliceSortedEqual(giteaKeys, providedKeys) {
log.Trace("synchronizePublicKeys[%s]: Public Keys are already in sync for %s (Source:%v/DB:%v)", s.Name, usr.Name, len(providedKeys), len(giteaKeys))
return false
return nil, nil
}
log.Trace("synchronizePublicKeys[%s]: Public Key needs update for user %s (Source:%v/DB:%v)", s.Name, usr.Name, len(providedKeys), len(giteaKeys))

Expand All @@ -429,9 +430,8 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
newKeys = append(newKeys, key)
}
}
if AddPublicKeysBySource(usr, s, newKeys) {
sshKeysNeedUpdate = true
}

addedKeys := AddPublicKeysBySource(usr, s, newKeys) // ToDo Audit

// Mark keys from DB that no longer exist in the source for deletion
var giteaKeysToDelete []string
Expand All @@ -443,13 +443,10 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
}

// Delete keys from DB that no longer exist in the source
needUpd, err := deleteKeysMarkedForDeletion(giteaKeysToDelete)
deletedKeys, err := deleteKeysMarkedForDeletion(giteaKeysToDelete)
if err != nil {
log.Error("synchronizePublicKeys[%s]: Error deleting Public Keys marked for deletion for user %s: %v", s.Name, usr.Name, err)
}
if needUpd {
sshKeysNeedUpdate = true
}

return sshKeysNeedUpdate
return addedKeys, deletedKeys
}
5 changes: 5 additions & 0 deletions models/db/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ func GetByBean(ctx context.Context, bean interface{}) (bool, error) {
return GetEngine(ctx).Get(bean)
}

// GetBeanByID
func GetBeanByID(ctx context.Context, id, bean interface{}) (bool, error) {
return GetEngine(ctx).ID(id).Get(bean)
}

// DeleteByBean deletes all records according non-empty fields of the bean as conditions.
func DeleteByBean(ctx context.Context, bean interface{}) (int64, error) {
return GetEngine(ctx).Delete(bean)
Expand Down
25 changes: 14 additions & 11 deletions models/org_team.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,36 +55,39 @@ func AddRepository(ctx context.Context, t *organization.Team, repo *repo_model.R

// addAllRepositories adds all repositories to the team.
// If the team already has some repositories they will be left unchanged.
func addAllRepositories(ctx context.Context, t *organization.Team) error {
func addAllRepositories(ctx context.Context, t *organization.Team) ([]*repo_model.Repository, error) {
orgRepos, err := organization.GetOrgRepositories(ctx, t.OrgID)
if err != nil {
return fmt.Errorf("get org repos: %w", err)
return nil, fmt.Errorf("get org repos: %w", err)
}

added := make([]*repo_model.Repository, 0, len(orgRepos))
for _, repo := range orgRepos {
if !organization.HasTeamRepo(ctx, t.OrgID, t.ID, repo.ID) {
if err := AddRepository(ctx, t, repo); err != nil {
return fmt.Errorf("AddRepository: %w", err)
return nil, fmt.Errorf("AddRepository: %w", err)
}
added = append(added, repo)
}
}

return nil
return added, nil
}

// AddAllRepositories adds all repositories to the team
func AddAllRepositories(t *organization.Team) (err error) {
func AddAllRepositories(t *organization.Team) ([]*repo_model.Repository, error) {
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return err
return nil, err
}
defer committer.Close()

if err = addAllRepositories(ctx, t); err != nil {
return err
added, err := addAllRepositories(ctx, t)
if err != nil {
return nil, err
}

return committer.Commit()
return added, committer.Commit()
}

// RemoveAllRepositories removes all repositories from team and recalculates access
Expand Down Expand Up @@ -283,7 +286,7 @@ func NewTeam(t *organization.Team) (err error) {

// Add all repositories to the team if it has access to all of them.
if t.IncludesAllRepositories {
err = addAllRepositories(ctx, t)
_, err = addAllRepositories(ctx, t)
if err != nil {
return fmt.Errorf("addAllRepositories: %w", err)
}
Expand Down Expand Up @@ -361,7 +364,7 @@ func UpdateTeam(t *organization.Team, authChanged, includeAllChanged bool) (err

// Add all repositories to the team if it has access to all of them.
if includeAllChanged && t.IncludesAllRepositories {
err = addAllRepositories(ctx, t)
_, err = addAllRepositories(ctx, t)
if err != nil {
return fmt.Errorf("addAllRepositories: %w", err)
}
Expand Down
5 changes: 5 additions & 0 deletions models/organization/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ func OrgFromUser(user *user_model.User) *Organization {
return (*Organization)(user)
}

// UserFromOrg converts organization to user
func UserFromOrg(org *Organization) *user_model.User {
return (*user_model.User)(org)
}

// TableName represents the real table name of Organization
func (Organization) TableName() string {
return "user"
Expand Down
1 change: 1 addition & 0 deletions models/system/notice.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
NoticeRepository NoticeType = iota + 1
// NoticeTask type
NoticeTask
NoticeAudit
)

// Notice represents a system notice for admin.
Expand Down
6 changes: 3 additions & 3 deletions models/user/email_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ func MakeEmailPrimary(email *EmailAddress) error {
}

// VerifyActiveEmailCode verifies active email code when active account
func VerifyActiveEmailCode(code, email string) *EmailAddress {
func VerifyActiveEmailCode(code, email string) (*User, *EmailAddress) {
minutes := setting.Service.ActiveCodeLives

if user := GetVerifyUser(code); user != nil {
Expand All @@ -411,11 +411,11 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress {
if base.VerifyTimeLimitCode(data, minutes, prefix) {
emailAddress := &EmailAddress{UID: user.ID, Email: email}
if has, _ := db.GetEngine(db.DefaultContext).Get(emailAddress); has {
return emailAddress
return user, emailAddress
}
}
}
return nil
return nil, nil
}

// SearchEmailOrderBy is used to sort the results from SearchEmails()
Expand Down
3 changes: 3 additions & 0 deletions modules/context/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/audit"
)

// APIContext is a specific context for API service
Expand Down Expand Up @@ -209,6 +210,8 @@ func (ctx *APIContext) CheckForOTP() {
return
}
if !ok {
audit.Record(audit.UserAuthenticationFailTwoFactor, ctx.Context.Doer, ctx.Context.Doer, twofa, "Failed two-factor authentication for user %s.", ctx.Context.Doer.Name)

ctx.Context.Error(http.StatusUnauthorized)
return
}
Expand Down
3 changes: 3 additions & 0 deletions modules/context/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/audit"
)

// ToggleOptions contains required or check options
Expand Down Expand Up @@ -173,6 +174,8 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
return
}
if !ok {
audit.Record(audit.UserAuthenticationFailTwoFactor, ctx.Doer, ctx.Doer, twofa, "Failed two-factor authentication for user %s.", ctx.Doer.Name)

ctx.JSON(http.StatusForbidden, map[string]string{
"message": "Only signed in user is allowed to call APIs.",
})
Expand Down
2 changes: 1 addition & 1 deletion modules/context/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
if ctx.Org == nil {
ctx.Org = &Organization{}
}
ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser)
ctx.Org.Organization = organization.OrgFromUser(ctx.ContextUser)
} else {
// ContextUser is an individual User
return
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3065,6 +3065,7 @@ notices.delete_all = Delete All Notices
notices.type = Type
notices.type_1 = Repository
notices.type_2 = Task
notices.type_3 = Audit
notices.desc = Description
notices.op = Op.
notices.delete_success = The system notices have been deleted.
Expand Down
3 changes: 3 additions & 0 deletions routers/api/v1/admin/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/audit"
"code.gitea.io/gitea/services/convert"
)

Expand Down Expand Up @@ -74,6 +75,8 @@ func CreateOrg(ctx *context.APIContext) {
return
}

audit.Record(audit.OrganizationCreate, ctx.Doer, org, org, "Organization %s was created.", org.Name)

ctx.JSON(http.StatusCreated, convert.ToOrganization(ctx, org))
}

Expand Down
Loading