mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-20 17:12:25 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			96 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2020 The Gitea Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package doctor
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 
 | |
| 	asymkey_model "code.gitea.io/gitea/models/asymkey"
 | |
| 	"code.gitea.io/gitea/modules/container"
 | |
| 	"code.gitea.io/gitea/modules/log"
 | |
| 	"code.gitea.io/gitea/modules/setting"
 | |
| )
 | |
| 
 | |
| const tplCommentPrefix = `# gitea public key`
 | |
| 
 | |
| func checkAuthorizedKeys(ctx context.Context, logger log.Logger, autofix bool) error {
 | |
| 	if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
 | |
| 	f, err := os.Open(fPath)
 | |
| 	if err != nil {
 | |
| 		if !autofix {
 | |
| 			logger.Critical("Unable to open authorized_keys file. ERROR: %v", err)
 | |
| 			return fmt.Errorf("Unable to open authorized_keys file. ERROR: %w", err)
 | |
| 		}
 | |
| 		logger.Warn("Unable to open authorized_keys. (ERROR: %v). Attempting to rewrite...", err)
 | |
| 		if err = asymkey_model.RewriteAllPublicKeys(ctx); err != nil {
 | |
| 			logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
 | |
| 			return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %w", err)
 | |
| 		}
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	linesInAuthorizedKeys := make(container.Set[string])
 | |
| 
 | |
| 	scanner := bufio.NewScanner(f)
 | |
| 	for scanner.Scan() {
 | |
| 		line := scanner.Text()
 | |
| 		if strings.HasPrefix(line, tplCommentPrefix) {
 | |
| 			continue
 | |
| 		}
 | |
| 		linesInAuthorizedKeys.Add(line)
 | |
| 	}
 | |
| 	f.Close()
 | |
| 
 | |
| 	// now we regenerate and check if there are any lines missing
 | |
| 	regenerated := &bytes.Buffer{}
 | |
| 	if err := asymkey_model.RegeneratePublicKeys(ctx, regenerated); err != nil {
 | |
| 		logger.Critical("Unable to regenerate authorized_keys file. ERROR: %v", err)
 | |
| 		return fmt.Errorf("Unable to regenerate authorized_keys file. ERROR: %w", err)
 | |
| 	}
 | |
| 	scanner = bufio.NewScanner(regenerated)
 | |
| 	for scanner.Scan() {
 | |
| 		line := scanner.Text()
 | |
| 		if strings.HasPrefix(line, tplCommentPrefix) {
 | |
| 			continue
 | |
| 		}
 | |
| 		if linesInAuthorizedKeys.Contains(line) {
 | |
| 			continue
 | |
| 		}
 | |
| 		if !autofix {
 | |
| 			logger.Critical(
 | |
| 				"authorized_keys file %q is out of date.\nRegenerate it with:\n\t\"%s\"\nor\n\t\"%s\"",
 | |
| 				fPath,
 | |
| 				"gitea admin regenerate keys",
 | |
| 				"gitea doctor --run authorized-keys --fix")
 | |
| 			return fmt.Errorf(`authorized_keys is out of date and should be regenerated with "gitea admin regenerate keys" or "gitea doctor --run authorized-keys --fix"`)
 | |
| 		}
 | |
| 		logger.Warn("authorized_keys is out of date. Attempting rewrite...")
 | |
| 		err = asymkey_model.RewriteAllPublicKeys(ctx)
 | |
| 		if err != nil {
 | |
| 			logger.Critical("Unable to rewrite authorized_keys file. ERROR: %v", err)
 | |
| 			return fmt.Errorf("Unable to rewrite authorized_keys file. ERROR: %w", err)
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func init() {
 | |
| 	Register(&Check{
 | |
| 		Title:     "Check if OpenSSH authorized_keys file is up-to-date",
 | |
| 		Name:      "authorized-keys",
 | |
| 		IsDefault: true,
 | |
| 		Run:       checkAuthorizedKeys,
 | |
| 		Priority:  4,
 | |
| 	})
 | |
| }
 |