Compare commits
5 Commits
f0230cd8c8
...
bf8dd2e441
| Author | SHA1 | Date | |
|---|---|---|---|
| bf8dd2e441 | |||
| 4cfecbdf76 | |||
| cf45778de0 | |||
| 930cea4617 | |||
| b80eea5c1f |
+17
-2179
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
package codit
|
||||
|
||||
import codit_config "codit/config"
|
||||
|
||||
// this public file is to workaround the import-cycle issue.
|
||||
// codit/config can't import from the root package.
|
||||
|
||||
type Config = codit_config.Config
|
||||
|
||||
type Duration = codit_config.Duration
|
||||
|
||||
func LoadConfig(path string) (Config, error) {
|
||||
return codit_config.Load(path)
|
||||
}
|
||||
|
||||
func LoadConfigWithEnvPrefix(path string, envPrefix string) (Config, error) {
|
||||
return codit_config.LoadWithEnvPrefix(path, envPrefix)
|
||||
}
|
||||
@@ -45,7 +45,15 @@ type Config struct {
|
||||
RPMHTTPPrefix string `json:"rpm_http_prefix"`
|
||||
}
|
||||
|
||||
const DefaultEnvPrefix string = "CODIT_"
|
||||
|
||||
type Duration time.Duration
|
||||
|
||||
func Load(path string) (Config, error) {
|
||||
return LoadWithEnvPrefix(path, DefaultEnvPrefix)
|
||||
}
|
||||
|
||||
func LoadWithEnvPrefix(path string, envPrefix string) (Config, error) {
|
||||
var cfg Config
|
||||
var data []byte
|
||||
var err error
|
||||
@@ -55,7 +63,7 @@ func Load(path string) (Config, error) {
|
||||
DataDir: "./codit-data",
|
||||
FrontendDir: filepath.Join("..", "frontend", "dist"),
|
||||
DBDriver: "sqlite",
|
||||
DBDSN: "file:./codit-data/codit.db?_pragma=foreign_keys(1)",
|
||||
DBDSN: "file:./codit-data/codit.db",
|
||||
SessionTTL: Duration(24 * time.Hour),
|
||||
AuthMode: "db",
|
||||
LDAPUserFilter: "(uid={username})",
|
||||
@@ -76,7 +84,7 @@ func Load(path string) (Config, error) {
|
||||
return cfg, err
|
||||
}
|
||||
}
|
||||
override(&cfg)
|
||||
override(&cfg, envPrefix)
|
||||
cfg.AuthMode = strings.ToLower(strings.TrimSpace(cfg.AuthMode))
|
||||
cfg.TLSServerCertSource = strings.ToLower(strings.TrimSpace(cfg.TLSServerCertSource))
|
||||
cfg.TLSClientAuth = strings.ToLower(strings.TrimSpace(cfg.TLSClientAuth))
|
||||
@@ -91,143 +99,147 @@ func Load(path string) (Config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func override(cfg *Config) {
|
||||
func override(cfg *Config, envPrefix string) {
|
||||
var v string
|
||||
v = os.Getenv("CODIT_HTTP_ADDRS")
|
||||
v = getEnv(envPrefix, "HTTP_ADDRS")
|
||||
if v != "" {
|
||||
cfg.HTTPAddrs = splitCSV(v)
|
||||
}
|
||||
v = os.Getenv("CODIT_HTTPS_ADDRS")
|
||||
v = getEnv(envPrefix, "HTTPS_ADDRS")
|
||||
if v != "" {
|
||||
cfg.HTTPSAddrs = splitCSV(v)
|
||||
}
|
||||
v = os.Getenv("CODIT_PUBLIC_BASE_URL")
|
||||
v = getEnv(envPrefix, "PUBLIC_BASE_URL")
|
||||
if v != "" {
|
||||
cfg.PublicBaseURL = v
|
||||
}
|
||||
v = os.Getenv("CODIT_DATA_DIR")
|
||||
v = getEnv(envPrefix, "DATA_DIR")
|
||||
if v != "" {
|
||||
cfg.DataDir = v
|
||||
}
|
||||
v = os.Getenv("CODIT_FRONTEND_DIR")
|
||||
v = getEnv(envPrefix, "FRONTEND_DIR")
|
||||
if v != "" {
|
||||
cfg.FrontendDir = v
|
||||
}
|
||||
v = os.Getenv("CODIT_DB_DRIVER")
|
||||
v = getEnv(envPrefix, "DB_DRIVER")
|
||||
if v != "" {
|
||||
cfg.DBDriver = v
|
||||
}
|
||||
v = os.Getenv("CODIT_DB_DSN")
|
||||
v = getEnv(envPrefix, "DB_DSN")
|
||||
if v != "" {
|
||||
cfg.DBDSN = v
|
||||
}
|
||||
v = os.Getenv("CODIT_AUTH_MODE")
|
||||
v = getEnv(envPrefix, "AUTH_MODE")
|
||||
if v != "" {
|
||||
cfg.AuthMode = v
|
||||
}
|
||||
v = os.Getenv("CODIT_LDAP_URL")
|
||||
v = getEnv(envPrefix, "LDAP_URL")
|
||||
if v != "" {
|
||||
cfg.LDAPURL = v
|
||||
}
|
||||
v = os.Getenv("CODIT_LDAP_BIND_DN")
|
||||
v = getEnv(envPrefix, "LDAP_BIND_DN")
|
||||
if v != "" {
|
||||
cfg.LDAPBindDN = v
|
||||
}
|
||||
v = os.Getenv("CODIT_LDAP_BIND_PASSWORD")
|
||||
v = getEnv(envPrefix, "LDAP_BIND_PASSWORD")
|
||||
if v != "" {
|
||||
cfg.LDAPBindPassword = v
|
||||
}
|
||||
v = os.Getenv("CODIT_LDAP_USER_BASE_DN")
|
||||
v = getEnv(envPrefix, "LDAP_USER_BASE_DN")
|
||||
if v != "" {
|
||||
cfg.LDAPUserBaseDN = v
|
||||
}
|
||||
v = os.Getenv("CODIT_LDAP_USER_FILTER")
|
||||
v = getEnv(envPrefix, "LDAP_USER_FILTER")
|
||||
if v != "" {
|
||||
cfg.LDAPUserFilter = v
|
||||
}
|
||||
v = os.Getenv("CODIT_LDAP_TLS_INSECURE_SKIP_VERIFY")
|
||||
v = getEnv(envPrefix, "LDAP_TLS_INSECURE_SKIP_VERIFY")
|
||||
if v != "" {
|
||||
cfg.LDAPTLSInsecureSkipVerify = parseEnvBool(v)
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_CLIENT_ID")
|
||||
v = getEnv(envPrefix, "OIDC_CLIENT_ID")
|
||||
if v != "" {
|
||||
cfg.OIDCClientID = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_CLIENT_SECRET")
|
||||
v = getEnv(envPrefix, "OIDC_CLIENT_SECRET")
|
||||
if v != "" {
|
||||
cfg.OIDCClientSecret = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_AUTHORIZE_URL")
|
||||
v = getEnv(envPrefix, "OIDC_AUTHORIZE_URL")
|
||||
if v != "" {
|
||||
cfg.OIDCAuthorizeURL = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_TOKEN_URL")
|
||||
v = getEnv(envPrefix, "OIDC_TOKEN_URL")
|
||||
if v != "" {
|
||||
cfg.OIDCTokenURL = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_USERINFO_URL")
|
||||
v = getEnv(envPrefix, "OIDC_USERINFO_URL")
|
||||
if v != "" {
|
||||
cfg.OIDCUserInfoURL = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_REDIRECT_URL")
|
||||
v = getEnv(envPrefix, "OIDC_REDIRECT_URL")
|
||||
if v != "" {
|
||||
cfg.OIDCRedirectURL = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_SCOPES")
|
||||
v = getEnv(envPrefix, "OIDC_SCOPES")
|
||||
if v != "" {
|
||||
cfg.OIDCScopes = v
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_ENABLED")
|
||||
v = getEnv(envPrefix, "OIDC_ENABLED")
|
||||
if v != "" {
|
||||
cfg.OIDCEnabled = parseEnvBool(v)
|
||||
}
|
||||
v = os.Getenv("CODIT_OIDC_TLS_INSECURE_SKIP_VERIFY")
|
||||
v = getEnv(envPrefix, "OIDC_TLS_INSECURE_SKIP_VERIFY")
|
||||
if v != "" {
|
||||
cfg.OIDCTLSInsecureSkipVerify = parseEnvBool(v)
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_SERVER_CERT_SOURCE")
|
||||
v = getEnv(envPrefix, "TLS_SERVER_CERT_SOURCE")
|
||||
if v != "" {
|
||||
cfg.TLSServerCertSource = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_CERT_FILE")
|
||||
v = getEnv(envPrefix, "TLS_CERT_FILE")
|
||||
if v != "" {
|
||||
cfg.TLSCertFile = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_KEY_FILE")
|
||||
v = getEnv(envPrefix, "TLS_KEY_FILE")
|
||||
if v != "" {
|
||||
cfg.TLSKeyFile = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_PKI_SERVER_CERT_ID")
|
||||
v = getEnv(envPrefix, "TLS_PKI_SERVER_CERT_ID")
|
||||
if v != "" {
|
||||
cfg.TLSPKIServerCertID = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_CLIENT_AUTH")
|
||||
v = getEnv(envPrefix, "TLS_CLIENT_AUTH")
|
||||
if v != "" {
|
||||
cfg.TLSClientAuth = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_CLIENT_CA_FILE")
|
||||
v = getEnv(envPrefix, "TLS_CLIENT_CA_FILE")
|
||||
if v != "" {
|
||||
cfg.TLSClientCAFile = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_PKI_CLIENT_CA_ID")
|
||||
v = getEnv(envPrefix, "TLS_PKI_CLIENT_CA_ID")
|
||||
if v != "" {
|
||||
cfg.TLSPKIClientCAID = v
|
||||
}
|
||||
v = os.Getenv("CODIT_TLS_MIN_VERSION")
|
||||
v = getEnv(envPrefix, "TLS_MIN_VERSION")
|
||||
if v != "" {
|
||||
cfg.TLSMinVersion = v
|
||||
}
|
||||
v = os.Getenv("CODIT_GIT_HTTP_PREFIX")
|
||||
v = getEnv(envPrefix, "GIT_HTTP_PREFIX")
|
||||
if v != "" {
|
||||
cfg.GitHTTPPrefix = v
|
||||
}
|
||||
v = os.Getenv("CODIT_RPM_HTTP_PREFIX")
|
||||
v = getEnv(envPrefix, "RPM_HTTP_PREFIX")
|
||||
if v != "" {
|
||||
cfg.RPMHTTPPrefix = v
|
||||
}
|
||||
}
|
||||
|
||||
type Duration time.Duration
|
||||
func getEnv(prefix string, name string) string {
|
||||
if prefix == "" { return os.Getenv(name) }
|
||||
return os.Getenv(prefix + name)
|
||||
}
|
||||
|
||||
|
||||
func (d Duration) Duration() time.Duration {
|
||||
return time.Duration(d)
|
||||
@@ -5,7 +5,7 @@ import "encoding/base64"
|
||||
import "errors"
|
||||
import "time"
|
||||
|
||||
import "codit/internal/config"
|
||||
import "codit/config"
|
||||
import "golang.org/x/crypto/bcrypt"
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import "strings"
|
||||
import "testing"
|
||||
import "time"
|
||||
|
||||
import "codit/internal/config"
|
||||
import "codit/config"
|
||||
|
||||
func TestHashAndComparePassword(t *testing.T) {
|
||||
var hash string
|
||||
|
||||
@@ -7,7 +7,7 @@ import "strings"
|
||||
import "time"
|
||||
import "crypto/tls"
|
||||
|
||||
import "codit/internal/config"
|
||||
import "codit/config"
|
||||
import "github.com/go-ldap/ldap/v3"
|
||||
|
||||
type LDAPUser struct {
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
package config
|
||||
|
||||
import "os"
|
||||
import "path/filepath"
|
||||
import "testing"
|
||||
import "time"
|
||||
|
||||
func TestLoadDefaults(t *testing.T) {
|
||||
var cfg Config
|
||||
var err error
|
||||
cfg, err = Load("")
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error: %v", err)
|
||||
}
|
||||
if cfg.DBDriver == "" || cfg.DBDSN == "" {
|
||||
t.Fatalf("defaults not populated: driver=%q dsn=%q", cfg.DBDriver, cfg.DBDSN)
|
||||
}
|
||||
if cfg.GitHTTPPrefix != "/git" {
|
||||
t.Fatalf("unexpected git prefix default: %s", cfg.GitHTTPPrefix)
|
||||
}
|
||||
if cfg.FrontendDir == "" {
|
||||
t.Fatalf("frontend_dir default missing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromJSONAndEnvOverride(t *testing.T) {
|
||||
var dir string
|
||||
var path string
|
||||
var data string
|
||||
var err error
|
||||
var cfg Config
|
||||
dir = t.TempDir()
|
||||
path = filepath.Join(dir, "config.json")
|
||||
data = `{"db_driver":"sqlite","db_dsn":"file:test.db","auth_mode":"HyBrId","git_http_prefix":"/g"}`
|
||||
err = os.WriteFile(path, []byte(data), 0o644)
|
||||
if err != nil {
|
||||
t.Fatalf("write config file: %v", err)
|
||||
}
|
||||
t.Setenv("CODIT_DB_DSN", "file:override.db")
|
||||
t.Setenv("CODIT_FRONTEND_DIR", "/srv/codit/frontend")
|
||||
cfg, err = Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error: %v", err)
|
||||
}
|
||||
if cfg.DBDSN != "file:override.db" {
|
||||
t.Fatalf("env override failed: %s", cfg.DBDSN)
|
||||
}
|
||||
if cfg.AuthMode != "hybrid" {
|
||||
t.Fatalf("auth_mode normalization failed: %s", cfg.AuthMode)
|
||||
}
|
||||
if cfg.FrontendDir != "/srv/codit/frontend" {
|
||||
t.Fatalf("frontend_dir env override failed: %s", cfg.FrontendDir)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDurationUnmarshalJSON(t *testing.T) {
|
||||
var d Duration
|
||||
var err error
|
||||
err = d.UnmarshalJSON([]byte(`"90m"`))
|
||||
if err != nil {
|
||||
t.Fatalf("UnmarshalJSON() string duration error: %v", err)
|
||||
}
|
||||
if d.Duration() != 90*time.Minute {
|
||||
t.Fatalf("unexpected duration: %v", d.Duration())
|
||||
}
|
||||
err = d.UnmarshalJSON([]byte(`60000000000`))
|
||||
if err != nil {
|
||||
t.Fatalf("UnmarshalJSON() numeric duration error: %v", err)
|
||||
}
|
||||
if d.Duration() != time.Duration(60000000000) {
|
||||
t.Fatalf("unexpected numeric duration: %v", d.Duration())
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package db
|
||||
import "context"
|
||||
import "database/sql"
|
||||
import "fmt"
|
||||
import "io/fs"
|
||||
import "os"
|
||||
import "path/filepath"
|
||||
import "sort"
|
||||
@@ -239,6 +240,86 @@ func (s *Store) ApplyMigrations(dir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) ApplyMigrationsFS(fsys fs.FS, dir string) error {
|
||||
var files []string
|
||||
var hasSchema bool
|
||||
var err error
|
||||
var applied bool
|
||||
var i int
|
||||
var version string
|
||||
var content []byte
|
||||
var initPath string
|
||||
|
||||
err = s.ensureSchemaMigrationsTable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, err = listMigrationFilesFS(fsys, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hasSchema, err = s.hasCoreSchema()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(files) == 0 {
|
||||
if hasSchema {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("no migration files found in %s", dir)
|
||||
}
|
||||
initPath, err = findMigrationPath(files, "001_init")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hasSchema {
|
||||
content, err = fs.ReadFile(fsys, initPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.Exec(string(content))
|
||||
if err != nil {
|
||||
return fmt.Errorf("apply %s: %w", filepath.Base(initPath), err)
|
||||
}
|
||||
err = s.markMigration("001_init")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = s.markMigration("001_init")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i = 0; i < len(files); i++ {
|
||||
version = migrationVersionFromPath(files[i])
|
||||
if version == "001_init" {
|
||||
continue
|
||||
}
|
||||
applied, err = s.hasMigration(version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if applied {
|
||||
continue
|
||||
}
|
||||
content, err = fs.ReadFile(fsys, files[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.Exec(string(content))
|
||||
if err != nil {
|
||||
return fmt.Errorf("apply %s: %w", filepath.Base(files[i]), err)
|
||||
}
|
||||
err = s.markMigration(version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) hasCoreSchema() (bool, error) {
|
||||
var row *sql.Row
|
||||
var value int
|
||||
@@ -340,6 +421,31 @@ func listMigrationFiles(dir string) ([]string, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func listMigrationFilesFS(fsys fs.FS, dir string) ([]string, error) {
|
||||
var entries []fs.DirEntry
|
||||
var files []string
|
||||
var err error
|
||||
var i int
|
||||
var name string
|
||||
|
||||
entries, err = fs.ReadDir(fsys, dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i = 0; i < len(entries); i++ {
|
||||
if entries[i].IsDir() {
|
||||
continue
|
||||
}
|
||||
name = entries[i].Name()
|
||||
if !strings.HasSuffix(strings.ToLower(name), ".sql") {
|
||||
continue
|
||||
}
|
||||
files = append(files, dir + "/" + name)
|
||||
}
|
||||
sort.Strings(files)
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func migrationVersionFromPath(path string) string {
|
||||
return strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import "codit/internal/db"
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
import codit_logger "codit/logger"
|
||||
|
||||
type AuthFunc func(username, password string) (bool, error)
|
||||
|
||||
@@ -23,12 +24,12 @@ type HTTPServer struct {
|
||||
store *db.Store
|
||||
baseDir string
|
||||
auth AuthFunc
|
||||
logger *util.Logger
|
||||
logger codit_logger.Logger
|
||||
}
|
||||
|
||||
const logIDDocker string = "docker"
|
||||
|
||||
func NewHTTPServer(store *db.Store, baseDir string, auth AuthFunc, logger *util.Logger) *HTTPServer {
|
||||
func NewHTTPServer(store *db.Store, baseDir string, auth AuthFunc, logger codit_logger.Logger) *HTTPServer {
|
||||
return &HTTPServer{
|
||||
store: store,
|
||||
baseDir: baseDir,
|
||||
@@ -59,7 +60,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !hasLogInfo {
|
||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
||||
}
|
||||
s.logger.Write(logIDDocker, util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d",
|
||||
s.logger.Write(logIDDocker, codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d",
|
||||
r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
}
|
||||
return
|
||||
@@ -74,7 +75,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !hasLogInfo {
|
||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
||||
}
|
||||
s.logger.Write(logIDDocker, util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d",
|
||||
s.logger.Write(logIDDocker, codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d",
|
||||
r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
}
|
||||
return
|
||||
@@ -88,7 +89,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !hasLogInfo {
|
||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
||||
}
|
||||
s.logger.Write(logIDDocker, util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d",
|
||||
s.logger.Write(logIDDocker, codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d",
|
||||
r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package git
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/util"
|
||||
import "net/http"
|
||||
import "os"
|
||||
import "path/filepath"
|
||||
@@ -12,12 +12,12 @@ import "github.com/sosedoff/gitkit"
|
||||
type HTTPServer struct {
|
||||
handler http.Handler
|
||||
baseDir string
|
||||
logger *util.Logger
|
||||
logger codit_logger.Logger
|
||||
}
|
||||
|
||||
type AuthFunc func(username, password string) (bool, error)
|
||||
|
||||
func NewHTTPServer(baseDir string, auth AuthFunc, logger *util.Logger) (*HTTPServer, error) {
|
||||
func NewHTTPServer(baseDir string, auth AuthFunc, logger codit_logger.Logger) (*HTTPServer, error) {
|
||||
var cfg gitkit.Config
|
||||
var srv *gitkit.Server
|
||||
cfg = gitkit.Config{
|
||||
@@ -74,7 +74,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
mtlsInfo = middleware.ClientCertLogFields(r)
|
||||
s.logger.Write(
|
||||
"git", util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d\n",
|
||||
"git", codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d\n",
|
||||
r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "context"
|
||||
import "bytes"
|
||||
import "crypto/ecdsa"
|
||||
@@ -21,7 +22,6 @@ import "time"
|
||||
import "golang.org/x/crypto/acme"
|
||||
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type acmeProfileRequest struct {
|
||||
Name string `json:"name"`
|
||||
@@ -98,7 +98,7 @@ func (api *API) CreateACMEProfile(w http.ResponseWriter, r *http.Request, _ map[
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request"})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "profile create requested name=%s directory=%s", strings.TrimSpace(req.Name), strings.TrimSpace(req.DirectoryURL))
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "profile create requested name=%s directory=%s", strings.TrimSpace(req.Name), strings.TrimSpace(req.DirectoryURL))
|
||||
item, err = normalizeACMEProfileRequest(req)
|
||||
if err != nil {
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
@@ -108,11 +108,11 @@ func (api *API) CreateACMEProfile(w http.ResponseWriter, r *http.Request, _ map[
|
||||
item.LastError = ""
|
||||
item, err = api.store(r).CreateACMEProfile(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "profile create failed name=%s err=%v", item.Name, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "profile create failed name=%s err=%v", item.Name, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "profile create success id=%s name=%s", item.ID, item.Name)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "profile create success id=%s name=%s", item.ID, item.Name)
|
||||
out = buildACMEProfileSummary(item)
|
||||
WriteJSON(w, http.StatusCreated, out)
|
||||
}
|
||||
@@ -157,11 +157,11 @@ func (api *API) UpdateACMEProfile(w http.ResponseWriter, r *http.Request, params
|
||||
item.Enabled = req.Enabled
|
||||
item, err = api.store(r).UpdateACMEProfile(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "profile update failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "profile update failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "profile update success id=%s name=%s enabled=%t", item.ID, item.Name, item.Enabled)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "profile update success id=%s name=%s enabled=%t", item.ID, item.Name, item.Enabled)
|
||||
out = buildACMEProfileSummary(item)
|
||||
WriteJSON(w, http.StatusOK, out)
|
||||
}
|
||||
@@ -173,11 +173,11 @@ func (api *API) DeleteACMEProfile(w http.ResponseWriter, r *http.Request, params
|
||||
}
|
||||
err = api.store(r).DeleteACMEProfile(params["id"])
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "profile delete failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "profile delete failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "profile delete success id=%s", params["id"])
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "profile delete success id=%s", params["id"])
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ func (api *API) RenewPKICertWithACME(w http.ResponseWriter, r *http.Request, par
|
||||
}
|
||||
sans = append(sans, part)
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order renew requested cert_id=%s profile=%s cn=%s", cert.ID, prev.ProfileID, cert.CommonName)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order renew requested cert_id=%s profile=%s cn=%s", cert.ID, prev.ProfileID, cert.CommonName)
|
||||
order, err = api.createACMEOrder(r.Context(), prev.ProfileID, cert.CommonName, sans, cert.ID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -362,7 +362,7 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
||||
var certKeyPEM string
|
||||
var csrPEM string
|
||||
var err error
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order create requested profile=%s cn=%s san_count=%d", strings.TrimSpace(profileID), strings.TrimSpace(commonName), len(sanDNS))
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order create requested profile=%s cn=%s san_count=%d", strings.TrimSpace(profileID), strings.TrimSpace(commonName), len(sanDNS))
|
||||
if strings.TrimSpace(profileID) == "" {
|
||||
return order, errors.New("profile_id is required")
|
||||
}
|
||||
@@ -389,19 +389,19 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
||||
}
|
||||
client, accountKey, profile, err = api.ensureACMEAccount(ctx, profile)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order create failed profile=%s step=account err=%v", profile.ID, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order create failed profile=%s step=account err=%v", profile.ID, err)
|
||||
_ = api.storeContext(ctx).UpdateACMEProfileLastError(profile.ID, err.Error())
|
||||
return order, err
|
||||
}
|
||||
_ = accountKey
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order create account ready profile=%s account=%s", profile.ID, profile.AccountURL)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order create account ready profile=%s account=%s", profile.ID, profile.AccountURL)
|
||||
rawOrder, err = client.AuthorizeOrder(context.Background(), domainIDs)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order create failed profile=%s step=authorize_order err=%v", profile.ID, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order create failed profile=%s step=authorize_order err=%v", profile.ID, err)
|
||||
_ = api.storeContext(ctx).UpdateACMEProfileLastError(profile.ID, err.Error())
|
||||
return order, err
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order created upstream profile=%s order_url=%s authz_count=%d", profile.ID, rawOrder.URI, len(rawOrder.AuthzURLs))
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order created upstream profile=%s order_url=%s authz_count=%d", profile.ID, rawOrder.URI, len(rawOrder.AuthzURLs))
|
||||
for i = 0; i < len(rawOrder.AuthzURLs); i++ {
|
||||
authz, err = client.GetAuthorization(context.Background(), rawOrder.AuthzURLs[i])
|
||||
if err != nil {
|
||||
@@ -430,7 +430,7 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
||||
DNSValue: txt,
|
||||
Status: ch.Status,
|
||||
})
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "dns challenge prepared order=%s domain=%s dns_name=%s", rawOrder.URI, authz.Identifier.Value, acmeDNSRecordName(authz.Identifier.Value))
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "dns challenge prepared order=%s domain=%s dns_name=%s", rawOrder.URI, authz.Identifier.Value, acmeDNSRecordName(authz.Identifier.Value))
|
||||
}
|
||||
order = models.ACMEOrder{
|
||||
ProfileID: profile.ID,
|
||||
@@ -447,10 +447,10 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
||||
}
|
||||
order, err = api.storeContext(ctx).CreateACMEOrder(order)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order create persist failed profile=%s order_url=%s err=%v", profile.ID, rawOrder.URI, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order create persist failed profile=%s order_url=%s err=%v", profile.ID, rawOrder.URI, err)
|
||||
return order, err
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order create success id=%s profile=%s cn=%s challenge_count=%d", order.ID, order.ProfileID, order.CommonName, len(order.Challenges))
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order create success id=%s profile=%s cn=%s challenge_count=%d", order.ID, order.ProfileID, order.CommonName, len(order.Challenges))
|
||||
_ = api.storeContext(ctx).UpdateACMEProfileLastError(profile.ID, "")
|
||||
return order, nil
|
||||
}
|
||||
@@ -497,7 +497,7 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "renew_mode must be override or new_cert"})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order finalize requested id=%s", params["id"])
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order finalize requested id=%s", params["id"])
|
||||
order, err = api.store(r).GetACMEOrder(params["id"])
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -518,7 +518,7 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
}
|
||||
client, accountKey, profile, err = api.ensureACMEAccount(r.Context(), profile)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order finalize failed id=%s step=account err=%v", order.ID, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order finalize failed id=%s step=account err=%v", order.ID, err)
|
||||
order.Status = "failed"
|
||||
order.LastError = err.Error()
|
||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
||||
@@ -538,13 +538,13 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
}
|
||||
if authz.Status == acme.StatusValid {
|
||||
order.Challenges[i].Status = acme.StatusValid
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "challenge already valid order=%s domain=%s", order.ID, order.Challenges[i].Identifier)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "challenge already valid order=%s domain=%s", order.ID, order.Challenges[i].Identifier)
|
||||
continue
|
||||
}
|
||||
if profile.SolverType == "acme_dns" {
|
||||
err = api.updateACMEDNSRecord(profile, order.Challenges[i])
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "challenge dns update failed order=%s domain=%s err=%v", order.ID, order.Challenges[i].Identifier, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "challenge dns update failed order=%s domain=%s err=%v", order.ID, order.Challenges[i].Identifier, err)
|
||||
order.Status = "failed"
|
||||
order.LastError = err.Error()
|
||||
order.Challenges[i].Status = "failed"
|
||||
@@ -553,7 +553,7 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "challenge dns updated order=%s domain=%s dns_name=%s", order.ID, order.Challenges[i].Identifier, order.Challenges[i].DNSName)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "challenge dns updated order=%s domain=%s dns_name=%s", order.ID, order.Challenges[i].Identifier, order.Challenges[i].DNSName)
|
||||
}
|
||||
challenge = &acme.Challenge{Type: "dns-01", URI: order.Challenges[i].ChallengeURL, Token: order.Challenges[i].Token}
|
||||
challenge, err = client.Accept(context.Background(), challenge)
|
||||
@@ -567,7 +567,7 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
}
|
||||
authz, err = client.WaitAuthorization(context.Background(), order.Challenges[i].AuthorizationURL)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "challenge wait failed order=%s domain=%s err=%v", order.ID, order.Challenges[i].Identifier, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "challenge wait failed order=%s domain=%s err=%v", order.ID, order.Challenges[i].Identifier, err)
|
||||
order.Status = "failed"
|
||||
order.LastError = err.Error()
|
||||
order.Challenges[i].Status = "failed"
|
||||
@@ -582,11 +582,11 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
break
|
||||
}
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "challenge finalized order=%s domain=%s status=%s", order.ID, order.Challenges[i].Identifier, order.Challenges[i].Status)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "challenge finalized order=%s domain=%s status=%s", order.ID, order.Challenges[i].Identifier, order.Challenges[i].Status)
|
||||
}
|
||||
certDER, certURL, err = client.CreateOrderCert(context.Background(), order.FinalizeURL, decodeCSRPEM(order.CSRPEM), true)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order finalize failed id=%s step=create_cert err=%v", order.ID, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order finalize failed id=%s step=create_cert err=%v", order.ID, err)
|
||||
order.Status = "failed"
|
||||
order.LastError = err.Error()
|
||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
||||
@@ -647,20 +647,20 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
cert.CAID = existing.CAID
|
||||
cert, err = api.store(r).ReplacePKICert(cert)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order finalize failed id=%s step=replace_cert err=%v", order.ID, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order finalize failed id=%s step=replace_cert err=%v", order.ID, err)
|
||||
order.Status = "failed"
|
||||
order.LastError = err.Error()
|
||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order finalize replaced existing cert id=%s", cert.ID)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order finalize replaced existing cert id=%s", cert.ID)
|
||||
}
|
||||
}
|
||||
if strings.TrimSpace(cert.ID) == "" {
|
||||
cert, err = api.store(r).CreatePKICert(cert)
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order finalize failed id=%s step=store_cert err=%v", order.ID, err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order finalize failed id=%s step=store_cert err=%v", order.ID, err)
|
||||
order.Status = "failed"
|
||||
order.LastError = err.Error()
|
||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
||||
@@ -678,7 +678,7 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
||||
}
|
||||
_ = api.store(r).UpdateACMEProfileLastError(profile.ID, "")
|
||||
_ = certURL
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order finalize success id=%s cert_id=%s cert_url=%s", order.ID, order.CertID, certURL)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order finalize success id=%s cert_id=%s cert_url=%s", order.ID, order.CertID, certURL)
|
||||
WriteJSON(w, http.StatusOK, order)
|
||||
}
|
||||
|
||||
@@ -689,11 +689,11 @@ func (api *API) DeleteACMEOrder(w http.ResponseWriter, r *http.Request, params m
|
||||
}
|
||||
err = api.store(r).DeleteACMEOrder(params["id"])
|
||||
if err != nil {
|
||||
api.Logger.Write(acmeLogID, util.LOG_WARN, "order delete failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_WARN, "order delete failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(acmeLogID, util.LOG_INFO, "order delete success id=%s", params["id"])
|
||||
api.Logger.Write(acmeLogID, codit_logger.LOG_INFO, "order delete success id=%s", params["id"])
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import "time"
|
||||
import "unicode"
|
||||
|
||||
import "codit/internal/auth"
|
||||
import "codit/internal/config"
|
||||
import "codit/config"
|
||||
import "codit/internal/db"
|
||||
import "codit/internal/docker"
|
||||
import "codit/internal/git"
|
||||
@@ -28,6 +28,7 @@ import "codit/internal/models"
|
||||
import "codit/internal/rpm"
|
||||
import "codit/internal/storage"
|
||||
import "codit/internal/util"
|
||||
import codit_logger "codit/logger"
|
||||
|
||||
type API struct {
|
||||
Cfg config.Config
|
||||
@@ -38,7 +39,7 @@ type API struct {
|
||||
RpmMirror *rpm.MirrorManager
|
||||
DockerBase string
|
||||
Uploads storage.FileStore
|
||||
Logger *util.Logger
|
||||
Logger codit_logger.Logger
|
||||
SSHSessionRegistry *SSHSessionRegistry
|
||||
SSHPromptedAuthStore *SSHPromptedAuthStore
|
||||
SSHPreparedSessionStore *SSHPreparedSessionStore
|
||||
@@ -386,10 +387,10 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ map[string]strin
|
||||
|
||||
authCfg, _ = api.effectiveAuthConfig(r.Context())
|
||||
if authCfg.AuthMode == "ldap" || authCfg.AuthMode == "hybrid" {
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "ldap login attempt username=%s mode=%s", req.Username, authCfg.AuthMode)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "ldap login attempt username=%s mode=%s", req.Username, authCfg.AuthMode)
|
||||
ldapUser, err = auth.LDAPAuthenticateContext(r.Context(), authCfg, req.Username, req.Password)
|
||||
if err == nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "ldap login success username=%s", req.Username)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "ldap login success username=%s", req.Username)
|
||||
if user.ID != "" && user.Disabled {
|
||||
WriteJSON(w, http.StatusForbidden, map[string]string{"error": "user disabled"})
|
||||
return
|
||||
@@ -413,7 +414,7 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ map[string]strin
|
||||
WriteJSON(w, http.StatusOK, user)
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDAuth, util.LOG_WARN, "ldap login failed username=%s err=%v", req.Username, err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_WARN, "ldap login failed username=%s err=%v", req.Username, err)
|
||||
}
|
||||
|
||||
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": "invalid credentials"})
|
||||
@@ -822,15 +823,15 @@ func (api *API) GetAuthSettings(w http.ResponseWriter, r *http.Request, _ map[st
|
||||
}
|
||||
user, ok = middleware.UserFromContext(r.Context())
|
||||
if ok {
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "auth settings fetch requested by user=%s", user.Username)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "auth settings fetch requested by user=%s", user.Username)
|
||||
}
|
||||
settings, err = api.getMergedAuthSettings(r.Context())
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_ERROR, "auth settings fetch failed err=%v", err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_ERROR, "auth settings fetch failed err=%v", err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "auth settings fetch success mode=%s ldap_url=%s oidc_authorize_url=%s", settings.AuthMode, settings.LDAPURL, settings.OIDCAuthorizeURL)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "auth settings fetch success mode=%s ldap_url=%s oidc_authorize_url=%s", settings.AuthMode, settings.LDAPURL, settings.OIDCAuthorizeURL)
|
||||
WriteJSON(w, http.StatusOK, settings)
|
||||
}
|
||||
|
||||
@@ -874,16 +875,16 @@ func (api *API) UpdateAuthSettings(w http.ResponseWriter, r *http.Request, _ map
|
||||
settings.OIDCScopes = "openid profile email"
|
||||
}
|
||||
if ok {
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "auth settings update requested by user=%s mode=%s oidc_enabled=%t ldap_url=%s oidc_authorize_url=%s",
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "auth settings update requested by user=%s mode=%s oidc_enabled=%t ldap_url=%s oidc_authorize_url=%s",
|
||||
user.Username, settings.AuthMode, settings.OIDCEnabled, settings.LDAPURL, settings.OIDCAuthorizeURL)
|
||||
}
|
||||
err = api.store(r).SetAuthSettings(settings)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_ERROR, "auth settings update failed err=%v", err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_ERROR, "auth settings update failed err=%v", err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "auth settings update success mode=%s oidc_enabled=%t ldap_url=%s oidc_authorize_url=%s", settings.AuthMode, settings.OIDCEnabled, settings.LDAPURL, settings.OIDCAuthorizeURL)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "auth settings update success mode=%s oidc_enabled=%t ldap_url=%s oidc_authorize_url=%s", settings.AuthMode, settings.OIDCEnabled, settings.LDAPURL, settings.OIDCAuthorizeURL)
|
||||
WriteJSON(w, http.StatusOK, settings)
|
||||
}
|
||||
|
||||
@@ -939,19 +940,19 @@ func (api *API) TestLDAPSettings(w http.ResponseWriter, r *http.Request, _ map[s
|
||||
cfg.LDAPUserFilter = merged.LDAPUserFilter
|
||||
err = auth.LDAPTestConnectionContext(r.Context(), cfg)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_WARN, "ldap test connection failed url=%s err=%v", cfg.LDAPURL, err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_WARN, "ldap test connection failed url=%s err=%v", cfg.LDAPURL, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "ldap test connection success url=%s", cfg.LDAPURL)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "ldap test connection success url=%s", cfg.LDAPURL)
|
||||
if strings.TrimSpace(req.Username) != "" && strings.TrimSpace(req.Password) != "" {
|
||||
user, err = auth.LDAPAuthenticateContext(r.Context(), cfg, strings.TrimSpace(req.Username), req.Password)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_WARN, "ldap test bind failed username=%s err=%v", strings.TrimSpace(req.Username), err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_WARN, "ldap test bind failed username=%s err=%v", strings.TrimSpace(req.Username), err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "ldap test bind success username=%s", user.Username)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "ldap test bind success username=%s", user.Username)
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "ok", "user": user.Username})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "context"
|
||||
import "crypto/rand"
|
||||
import "crypto/sha1"
|
||||
@@ -16,9 +17,8 @@ import "net/url"
|
||||
import "strings"
|
||||
import "time"
|
||||
|
||||
import "codit/internal/config"
|
||||
import "codit/config"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type oidcTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
@@ -91,7 +91,7 @@ func (api *API) OIDCLogin(w http.ResponseWriter, r *http.Request, _ map[string]s
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
authURL = api.buildOIDCAuthorizeURL(cfg, state)
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "oidc login redirect authorize_url=%s", cfg.OIDCAuthorizeURL)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "oidc login redirect authorize_url=%s", cfg.OIDCAuthorizeURL)
|
||||
http.Redirect(w, r, authURL, http.StatusFound)
|
||||
}
|
||||
|
||||
@@ -137,24 +137,24 @@ func (api *API) OIDCCallback(w http.ResponseWriter, r *http.Request, _ map[strin
|
||||
}
|
||||
token, err = api.oidcExchangeCode(r.Context(), cfg, code)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_WARN, "oidc token exchange failed err=%v", err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_WARN, "oidc token exchange failed err=%v", err)
|
||||
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
claims, err = api.oidcResolveClaims(r.Context(), cfg, token)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_WARN, "oidc claims fetch failed err=%v", err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_WARN, "oidc claims fetch failed err=%v", err)
|
||||
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": "oidc claims fetch failed"})
|
||||
return
|
||||
}
|
||||
user, err = api.oidcGetOrCreateUser(r.Context(), claims)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDAuth, util.LOG_WARN, "oidc user mapping failed err=%v", err)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_WARN, "oidc user mapping failed err=%v", err)
|
||||
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": "oidc user mapping failed"})
|
||||
return
|
||||
}
|
||||
api.issueSession(w, r, user)
|
||||
api.Logger.Write(logIDAuth, util.LOG_INFO, "oidc login success username=%s", user.Username)
|
||||
api.Logger.Write(logIDAuth, codit_logger.LOG_INFO, "oidc login success username=%s", user.Username)
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "archive/zip"
|
||||
import "bytes"
|
||||
import "context"
|
||||
@@ -27,7 +28,6 @@ import "time"
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/pkiutil"
|
||||
import "codit/internal/util"
|
||||
|
||||
type pkiCreateRootRequest struct {
|
||||
Name string `json:"name"`
|
||||
@@ -1058,7 +1058,7 @@ func (api *API) DownloadPKICertBundle(w http.ResponseWriter, r *http.Request, pa
|
||||
chainCount++
|
||||
}
|
||||
}
|
||||
api.Logger.Write(logIDPKI, util.LOG_INFO, "cert bundle cert=%s ca_id=%s ca_chain_entries=%d expected_cert_blocks=%d", cert.ID, cert.CAID, chainCount, 1+chainCount)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_INFO, "cert bundle cert=%s ca_id=%s ca_chain_entries=%d expected_cert_blocks=%d", cert.ID, cert.CAID, chainCount, 1+chainCount)
|
||||
data, err = buildPKIZipBundle(cert.CommonName, cert.CertPEM, cert.KeyPEM, false, caPEMs)
|
||||
if err != nil {
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "crypto/rand"
|
||||
import "crypto/rsa"
|
||||
import "crypto/x509"
|
||||
@@ -20,7 +21,6 @@ import "time"
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/pkiutil"
|
||||
import "codit/internal/util"
|
||||
|
||||
const logIDPKI string = "pki"
|
||||
const pkiClientMinValidSeconds int64 = 60
|
||||
@@ -215,11 +215,11 @@ func (api *API) CreatePKIClientProfile(w http.ResponseWriter, r *http.Request, _
|
||||
}
|
||||
item, err = api.store(r).CreatePKIClientProfile(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDPKI, util.LOG_WARN, "client profile create failed name=%s err=%v", item.Name, err)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile create failed name=%s err=%v", item.Name, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDPKI, util.LOG_INFO, "client profile create success id=%s name=%s targets=%d", item.ID, item.Name, len(item.Targets))
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_INFO, "client profile create success id=%s name=%s targets=%d", item.ID, item.Name, len(item.Targets))
|
||||
WriteJSON(w, http.StatusCreated, buildPKIClientProfileSummary(item))
|
||||
}
|
||||
|
||||
@@ -298,11 +298,11 @@ func (api *API) UpdatePKIClientProfile(w http.ResponseWriter, r *http.Request, p
|
||||
}
|
||||
existing, err = api.store(r).UpdatePKIClientProfile(existing)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDPKI, util.LOG_WARN, "client profile update failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile update failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDPKI, util.LOG_INFO, "client profile update success id=%s name=%s", existing.ID, existing.Name)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_INFO, "client profile update success id=%s name=%s", existing.ID, existing.Name)
|
||||
WriteJSON(w, http.StatusOK, buildPKIClientProfileSummary(existing))
|
||||
}
|
||||
|
||||
@@ -314,11 +314,11 @@ func (api *API) DeletePKIClientProfile(w http.ResponseWriter, r *http.Request, p
|
||||
}
|
||||
err = api.store(r).DeletePKIClientProfile(params["id"])
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDPKI, util.LOG_WARN, "client profile delete failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile delete failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDPKI, util.LOG_INFO, "client profile delete success id=%s", params["id"])
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_INFO, "client profile delete success id=%s", params["id"])
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||
}
|
||||
|
||||
@@ -456,7 +456,7 @@ func (api *API) IssuePKIClientCertForSelf(w http.ResponseWriter, r *http.Request
|
||||
serialHex = strconv.FormatInt(serial, 16)
|
||||
certPEM, keyPEM, notBefore, notAfter, err = issuePKIClientCertFromProfile(ca, serial, user, profile, permissions, commonName, sanDNS, sanIPs, sanURI, validSeconds)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDPKI, util.LOG_WARN, "client cert issue failed user=%s profile=%s err=%v", user.Username, profile.ID, err)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client cert issue failed user=%s profile=%s err=%v", user.Username, profile.ID, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@@ -512,7 +512,7 @@ func (api *API) IssuePKIClientCertForSelf(w http.ResponseWriter, r *http.Request
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDPKI, util.LOG_INFO, "client cert issue success user=%s profile=%s cert=%s perms=%s scope=%s", user.Username, profile.ID, cert.ID, profile.AuthzPermissions, profile.AuthzScope)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_INFO, "client cert issue success user=%s profile=%s cert=%s perms=%s scope=%s", user.Username, profile.ID, cert.ID, profile.AuthzPermissions, profile.AuthzScope)
|
||||
WriteJSON(w, http.StatusCreated, pkiClientIssueResponse{
|
||||
Issuance: buildPKIClientIssuanceSummary(issuance),
|
||||
CertPEM: cert.CertPEM,
|
||||
@@ -672,7 +672,7 @@ func (api *API) RevokePKIClientCertForSelf(w http.ResponseWriter, r *http.Reques
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDPKI, util.LOG_INFO, "client cert revoke success user=%s cert=%s", user.Username, cert.ID)
|
||||
api.Logger.Write(logIDPKI, codit_logger.LOG_INFO, "client cert revoke success user=%s cert=%s", user.Username, cert.ID)
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "revoked"})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "database/sql"
|
||||
import "encoding/base64"
|
||||
import "errors"
|
||||
@@ -19,7 +20,6 @@ import "golang.org/x/net/websocket"
|
||||
import "codit/internal/db"
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
const logIDSSHBroker string = "ssh-broker"
|
||||
type sshServerRequest struct {
|
||||
@@ -122,7 +122,7 @@ const sshSecondFactorNone string = "none"
|
||||
const sshSecondFactorPromptedTOTP string = "prompted_totp"
|
||||
|
||||
func (api *API) logSSHSessionConnectStart(sessionItem models.SSHSession, profile models.SSHAccessProfile, user models.User) {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"connect start session=%s requester=%s user=%s profile=%s profile_name=%q server=%s server_name=%q target=%s:%d remote_user=%s auth=%s",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
@@ -138,7 +138,7 @@ func (api *API) logSSHSessionConnectStart(sessionItem models.SSHSession, profile
|
||||
}
|
||||
|
||||
func (api *API) logSSHSessionPrepare(sessionID string, remoteAddr string, user models.User, profile models.SSHAccessProfile) {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"connect prepare session=%s requester=%s user=%s profile=%s profile_name=%q server=%s server_name=%q target=%s:%d remote_user=%s auth=%s",
|
||||
sessionID,
|
||||
remoteAddr,
|
||||
@@ -154,7 +154,7 @@ func (api *API) logSSHSessionPrepare(sessionID string, remoteAddr string, user m
|
||||
}
|
||||
|
||||
func (api *API) logSSHSessionConnectSuccess(sessionItem models.SSHSession, profile models.SSHAccessProfile, user models.User, hostKeyFingerprint string) {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"connect success session=%s requester=%s user=%s profile=%s profile_name=%q server=%s server_name=%q target=%s:%d remote_user=%s auth=%s host_key=%s",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
@@ -171,7 +171,7 @@ func (api *API) logSSHSessionConnectSuccess(sessionItem models.SSHSession, profi
|
||||
}
|
||||
|
||||
func (api *API) logSSHSessionConnectFailure(sessionItem models.SSHSession, profile models.SSHAccessProfile, user models.User, stage string, err error) {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_WARN,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN,
|
||||
"connect failed session=%s requester=%s user=%s profile=%s profile_name=%q server=%s server_name=%q target=%s:%d remote_user=%s auth=%s stage=%s err=%v",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
@@ -189,7 +189,7 @@ func (api *API) logSSHSessionConnectFailure(sessionItem models.SSHSession, profi
|
||||
}
|
||||
|
||||
func (api *API) logSSHSessionPrepareFailure(sessionID string, remoteAddr string, username string, profileID string, stage string, err error) {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_WARN,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN,
|
||||
"connect failed session=%s requester=%s user=%s profile=%s stage=%s err=%v",
|
||||
sessionID,
|
||||
remoteAddr,
|
||||
@@ -206,7 +206,7 @@ func (api *API) logSSHSessionClosed(sessionItem models.SSHSession, profile model
|
||||
if connectedAt > 0 && endedAt >= connectedAt {
|
||||
durationSeconds = endedAt - connectedAt
|
||||
}
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"session closed session=%s requester=%s user=%s profile=%s profile_name=%q server=%s server_name=%q target=%s:%d remote_user=%s auth=%s status=%s dur_s=%d reason=%q",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
@@ -1860,7 +1860,7 @@ event_loop:
|
||||
for {
|
||||
select {
|
||||
case err = <-controlErrCh:
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_WARN,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN,
|
||||
"workspace stream closed requester=%s user=%s err=%v",
|
||||
remoteAddr,
|
||||
user.Username,
|
||||
@@ -1920,7 +1920,7 @@ event_loop:
|
||||
InputErrCh: make(chan error, 1),
|
||||
}
|
||||
attachments[msg.SessionID] = attachment
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"workspace attach session=%s requester=%s user=%s",
|
||||
msg.SessionID,
|
||||
remoteAddr,
|
||||
@@ -2172,7 +2172,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
||||
}
|
||||
transcriptRecorder, err = api.openSSHSessionTranscriptRecorder(sessionItem.ID)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_WARN,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN,
|
||||
"transcript open failed session=%s err=%v",
|
||||
sessionItem.ID,
|
||||
err)
|
||||
@@ -2225,7 +2225,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
||||
}
|
||||
}
|
||||
}
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"session loop ended session=%s requester=%s user=%s profile=%s profile_name=%q source=%s wait_err=%v",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
@@ -2247,7 +2247,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
||||
}
|
||||
if waitErr != nil && !isSSHSessionTerminalExit(waitErr) {
|
||||
_ = store.UpdateSSHSessionStatus(sessionItem.ID, "error", connectedFingerprint, connectedAt, now, waitErr.Error())
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_WARN,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN,
|
||||
"session error session=%s requester=%s user=%s profile=%s profile_name=%q server=%s server_name=%q target=%s:%d remote_user=%s auth=%s dur_s=%d err=%v",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
@@ -2268,7 +2268,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
||||
return
|
||||
}
|
||||
if isSSHSessionTerminalExit(waitErr) {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_INFO,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_INFO,
|
||||
"session ended session=%s requester=%s user=%s profile=%s profile_name=%q err=%v",
|
||||
sessionItem.ID,
|
||||
sessionItem.RemoteAddr,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "database/sql"
|
||||
import "fmt"
|
||||
import "io"
|
||||
@@ -11,7 +12,6 @@ import "sync"
|
||||
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type sshSessionTranscriptRecorder struct {
|
||||
mu sync.Mutex
|
||||
@@ -201,7 +201,7 @@ func (api *API) writeSSHSessionTranscriptChunk(sessionID string, data []byte, re
|
||||
}
|
||||
err = recorder.Write(data)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHBroker, util.LOG_WARN,
|
||||
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN,
|
||||
"transcript write failed session=%s err=%v",
|
||||
sessionID,
|
||||
err)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "database/sql"
|
||||
import "errors"
|
||||
import "net/http"
|
||||
@@ -8,7 +9,6 @@ import "time"
|
||||
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type sshPrincipalGrantTargetRequest struct {
|
||||
TargetType string `json:"target_type"`
|
||||
@@ -184,11 +184,11 @@ func (api *API) CreateSSHPrincipalGrant(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
item, err = api.store(r).CreateSSHPrincipalGrant(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "grant create failed name=%s err=%v", name, err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant create failed name=%s err=%v", name, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "grant create success id=%s name=%s principals=%d targets=%d", item.ID, item.Name, len(item.Principals), len(item.Targets))
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "grant create success id=%s name=%s principals=%d targets=%d", item.ID, item.Name, len(item.Principals), len(item.Targets))
|
||||
WriteJSON(w, http.StatusCreated, buildSSHPrincipalGrantSummary(item))
|
||||
}
|
||||
|
||||
@@ -256,11 +256,11 @@ func (api *API) UpdateSSHPrincipalGrant(w http.ResponseWriter, r *http.Request,
|
||||
item.Targets = targets
|
||||
item, err = api.store(r).UpdateSSHPrincipalGrant(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "grant update failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant update failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "grant update success id=%s name=%s principals=%d targets=%d", item.ID, item.Name, len(item.Principals), len(item.Targets))
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "grant update success id=%s name=%s principals=%d targets=%d", item.ID, item.Name, len(item.Principals), len(item.Targets))
|
||||
WriteJSON(w, http.StatusOK, buildSSHPrincipalGrantSummary(item))
|
||||
}
|
||||
|
||||
@@ -271,11 +271,11 @@ func (api *API) DeleteSSHPrincipalGrant(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
err = api.store(r).DeleteSSHPrincipalGrant(params["id"])
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "grant delete failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant delete failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "grant delete success id=%s", params["id"])
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "grant delete success id=%s", params["id"])
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "crypto/ed25519"
|
||||
import "crypto/ecdsa"
|
||||
import "crypto/elliptic"
|
||||
@@ -22,7 +23,6 @@ import "golang.org/x/crypto/ssh"
|
||||
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type sshUserCACreateRequest struct {
|
||||
Name string `json:"name"`
|
||||
@@ -207,12 +207,12 @@ func (api *API) CreateSSHUserCA(w http.ResponseWriter, r *http.Request, _ map[st
|
||||
}
|
||||
item, err = api.store(r).CreateSSHUserCA(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "create failed name=%s err=%v", req.Name, err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "create failed name=%s err=%v", req.Name, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
summary = buildSSHUserCASummary(item)
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "create success id=%s name=%s algorithm=%s", summary.ID, summary.Name, summary.Algorithm)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "create success id=%s name=%s algorithm=%s", summary.ID, summary.Name, summary.Algorithm)
|
||||
WriteJSON(w, http.StatusCreated, summary)
|
||||
}
|
||||
|
||||
@@ -254,11 +254,11 @@ func (api *API) UpdateSSHUserCA(w http.ResponseWriter, r *http.Request, params m
|
||||
item.MaxUserValidSeconds = maxUserValidSeconds
|
||||
item, err = api.store(r).UpdateSSHUserCA(item)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "update failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "update failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "update success id=%s name=%s enabled=%t", item.ID, item.Name, item.Enabled)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "update success id=%s name=%s enabled=%t", item.ID, item.Name, item.Enabled)
|
||||
WriteJSON(w, http.StatusOK, buildSSHUserCASummary(item))
|
||||
}
|
||||
|
||||
@@ -269,11 +269,11 @@ func (api *API) DeleteSSHUserCA(w http.ResponseWriter, r *http.Request, params m
|
||||
}
|
||||
err = api.store(r).DeleteSSHUserCA(params["id"])
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "delete failed id=%s err=%v", params["id"], err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "delete failed id=%s err=%v", params["id"], err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "delete success id=%s", params["id"])
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "delete success id=%s", params["id"])
|
||||
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||
}
|
||||
|
||||
@@ -385,11 +385,11 @@ func (api *API) SignSSHUserKey(w http.ResponseWriter, r *http.Request, params ma
|
||||
}
|
||||
err = api.recordSSHUserCAIssuance(r, item, user, "admin", sourcePublicKey, sourcePublicKeyFingerprint, nil, nil, response)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "audit write failed ca_id=%s serial=%d err=%v", item.ID, response.Serial, err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "audit write failed ca_id=%s serial=%d err=%v", item.ID, response.Serial, err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to record issuance audit"})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "sign success ca_id=%s serial=%d key_id=%s principals=%s", item.ID, response.Serial, response.KeyID, strings.Join(principals, ","))
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "sign success ca_id=%s serial=%d key_id=%s principals=%s", item.ID, response.Serial, response.KeyID, strings.Join(principals, ","))
|
||||
WriteJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
@@ -720,18 +720,18 @@ func (api *API) SignSSHUserKeyForSelf(w http.ResponseWriter, r *http.Request, pa
|
||||
for grantID = range selectedGrantIDs {
|
||||
err = api.store(r).MarkSSHPrincipalGrantUsed(grantID)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "self-sign grant consume failed ca_id=%s user=%s grant_id=%s err=%v", item.ID, user.Username, grantID, err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "self-sign grant consume failed ca_id=%s user=%s grant_id=%s err=%v", item.ID, user.Username, grantID, err)
|
||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "selected principal grant is not active"})
|
||||
return
|
||||
}
|
||||
}
|
||||
err = api.recordSSHUserCAIssuance(r, item, user, "self", sourcePublicKey, sourcePublicKeyFingerprint, selectedIDs, selectedGrantNames, response)
|
||||
if err != nil {
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_WARN, "self-sign audit write failed ca_id=%s user=%s serial=%d err=%v", item.ID, user.Username, response.Serial, err)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "self-sign audit write failed ca_id=%s user=%s serial=%d err=%v", item.ID, user.Username, response.Serial, err)
|
||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to record issuance audit"})
|
||||
return
|
||||
}
|
||||
api.Logger.Write(logIDSSHCA, util.LOG_INFO, "self-sign success ca_id=%s user=%s serial=%d key_id=%s", item.ID, user.Username, response.Serial, response.KeyID)
|
||||
api.Logger.Write(logIDSSHCA, codit_logger.LOG_INFO, "self-sign success ca_id=%s user=%s serial=%d key_id=%s", item.ID, user.Username, response.Serial, response.KeyID)
|
||||
WriteJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package middleware
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "bufio"
|
||||
import "fmt"
|
||||
import "io"
|
||||
@@ -8,7 +9,6 @@ import "net/http"
|
||||
import "time"
|
||||
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type statusRecorder struct {
|
||||
http.ResponseWriter
|
||||
@@ -75,7 +75,7 @@ func (r *statusRecorder) ReadFrom(src io.Reader) (int64, error) {
|
||||
return io.Copy(r.ResponseWriter, src)
|
||||
}
|
||||
|
||||
func AccessLog(logger *util.Logger, next http.Handler) http.Handler {
|
||||
func AccessLog(logger codit_logger.Logger, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var recorder *statusRecorder
|
||||
var start time.Time
|
||||
@@ -104,7 +104,7 @@ func AccessLog(logger *util.Logger, next http.Handler) http.Handler {
|
||||
if !ok || authReason == "" {
|
||||
authReason = "-"
|
||||
}
|
||||
logger.Write(logIDAPI, util.LOG_INFO, "method=%s path=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d dur_ms=%d auth_reason=%s",
|
||||
logger.Write(logIDAPI, codit_logger.LOG_INFO, "method=%s path=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d dur_ms=%d auth_reason=%s",
|
||||
r.Method, r.URL.Path, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status, duration.Milliseconds(), authReason)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,24 +1,46 @@
|
||||
package middleware
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "bytes"
|
||||
import "context"
|
||||
import "fmt"
|
||||
import "net/http"
|
||||
import "net/http/httptest"
|
||||
import "strings"
|
||||
import "testing"
|
||||
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
type testLogger struct {
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
func (l *testLogger) Write(id string, level codit_logger.LogLevel, fmtstr string, args ...interface{}) {
|
||||
var line string
|
||||
|
||||
line = fmt.Sprintf(fmtstr, args...)
|
||||
l.buf.WriteString(line)
|
||||
}
|
||||
|
||||
func (l *testLogger) WriteWithCallDepth(id string, level codit_logger.LogLevel, call_depth int, fmtstr string, args ...interface{}) {
|
||||
l.Write(id, level, fmtstr, args...)
|
||||
}
|
||||
|
||||
func (l *testLogger) Rotate() {
|
||||
}
|
||||
|
||||
func (l *testLogger) Close() {
|
||||
}
|
||||
|
||||
func TestAccessLogWritesRecord(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
var logger *util.Logger
|
||||
var logger codit_logger.Logger
|
||||
var handler http.Handler
|
||||
var req *http.Request
|
||||
var recorder *httptest.ResponseRecorder
|
||||
var user models.User
|
||||
var ctx context.Context
|
||||
logger = util.NewLogger("test", &buf, util.LOG_ALL)
|
||||
logger = &testLogger{buf: &buf}
|
||||
defer logger.Close()
|
||||
handler = AccessLog(logger, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
@@ -15,7 +15,7 @@ func WithCors(next http.Handler) http.Handler {
|
||||
h.Add("Access-Control-Allow-Methods", "*")
|
||||
h.Add("Access-Control-Allow-Origin", "*")
|
||||
|
||||
if r.Method == "OPTIONS" {
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package rpm
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "codit/internal/middleware"
|
||||
import "codit/internal/util"
|
||||
import "net/http"
|
||||
|
||||
type HTTPServer struct {
|
||||
handler http.Handler
|
||||
auth AuthFunc
|
||||
logger *util.Logger
|
||||
logger codit_logger.Logger
|
||||
}
|
||||
|
||||
type AuthFunc func(username, password string) (bool, error)
|
||||
|
||||
const logIDRPM string = "rpm"
|
||||
|
||||
func NewHTTPServer(baseDir string, auth AuthFunc, logger *util.Logger) *HTTPServer {
|
||||
func NewHTTPServer(baseDir string, auth AuthFunc, logger codit_logger.Logger) *HTTPServer {
|
||||
var server HTTPServer
|
||||
server = HTTPServer{
|
||||
handler: http.FileServer(http.Dir(baseDir)),
|
||||
@@ -47,7 +47,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !hasLogInfo {
|
||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
||||
}
|
||||
s.logger.Write(logIDRPM, util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d", r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
s.logger.Write(logIDRPM, codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d", r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
return
|
||||
}
|
||||
allowed, err = s.auth(username, password)
|
||||
@@ -59,7 +59,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !hasLogInfo {
|
||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
||||
}
|
||||
s.logger.Write(logIDRPM, util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d", r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
s.logger.Write(logIDRPM, codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d", r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
return
|
||||
}
|
||||
userLabel = username
|
||||
@@ -69,7 +69,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !hasLogInfo {
|
||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
||||
}
|
||||
s.logger.Write(logIDRPM, util.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d", r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
s.logger.Write(logIDRPM, codit_logger.LOG_INFO, "method=%s path=%s orgpath=%s project_id=%s project_slug=%s repo_id=%s repo_name=%s remote=%s user=%s mtls_cn=%q mtls_issuer_cn=%q mtls_serial=%q mtls_user_id=%q mtls_username=%q mtls_profile_id=%q mtls_permissions=%q mtls_scope=%q status=%d", r.Method, r.URL.Path, logInfo.OrgPath, logInfo.ProjectID, logInfo.ProjectSlug, logInfo.RepoID, logInfo.RepoName, r.RemoteAddr, userLabel, mtlsInfo.SubjectCN, mtlsInfo.IssuerCN, mtlsInfo.Serial, mtlsInfo.UserID, mtlsInfo.Username, mtlsInfo.ProfileID, mtlsInfo.Permissions, mtlsInfo.Scope, recorder.status)
|
||||
}
|
||||
|
||||
type statusRecorder struct {
|
||||
|
||||
@@ -1,22 +1,35 @@
|
||||
package rpm
|
||||
|
||||
import "bytes"
|
||||
import codit_logger "codit/logger"
|
||||
import "net/http"
|
||||
import "net/http/httptest"
|
||||
import "os"
|
||||
import "path/filepath"
|
||||
import "testing"
|
||||
|
||||
import "codit/internal/util"
|
||||
type testLogger struct {
|
||||
}
|
||||
|
||||
func (l *testLogger) Write(id string, level codit_logger.LogLevel, fmtstr string, args ...interface{}) {
|
||||
}
|
||||
|
||||
func (l *testLogger) WriteWithCallDepth(id string, level codit_logger.LogLevel, call_depth int, fmtstr string, args ...interface{}) {
|
||||
}
|
||||
|
||||
func (l *testLogger) Rotate() {
|
||||
}
|
||||
|
||||
func (l *testLogger) Close() {
|
||||
}
|
||||
|
||||
func TestHTTPServerUnauthorizedWithoutBasicAuth(t *testing.T) {
|
||||
var dir string
|
||||
var logger *util.Logger
|
||||
var logger codit_logger.Logger
|
||||
var server *HTTPServer
|
||||
var req *http.Request
|
||||
var recorder *httptest.ResponseRecorder
|
||||
dir = t.TempDir()
|
||||
logger = util.NewLogger("test", &bytes.Buffer{}, util.LOG_ALL)
|
||||
logger = &testLogger{}
|
||||
defer logger.Close()
|
||||
server = NewHTTPServer(dir, func(username, password string) (bool, error) {
|
||||
return true, nil
|
||||
@@ -31,7 +44,7 @@ func TestHTTPServerUnauthorizedWithoutBasicAuth(t *testing.T) {
|
||||
|
||||
func TestHTTPServerAuthorized(t *testing.T) {
|
||||
var dir string
|
||||
var logger *util.Logger
|
||||
var logger codit_logger.Logger
|
||||
var server *HTTPServer
|
||||
var req *http.Request
|
||||
var recorder *httptest.ResponseRecorder
|
||||
@@ -39,7 +52,7 @@ func TestHTTPServerAuthorized(t *testing.T) {
|
||||
dir = t.TempDir()
|
||||
path = filepath.Join(dir, "a.txt")
|
||||
_ = os.WriteFile(path, []byte("ok"), 0o644)
|
||||
logger = util.NewLogger("test", &bytes.Buffer{}, util.LOG_ALL)
|
||||
logger = &testLogger{}
|
||||
defer logger.Close()
|
||||
server = NewHTTPServer(dir, func(username, password string) (bool, error) {
|
||||
return username == "u" && password == "p", nil
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package rpm
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
import "compress/gzip"
|
||||
import "context"
|
||||
import "crypto/md5"
|
||||
@@ -26,13 +27,12 @@ import "time"
|
||||
|
||||
import "codit/internal/db"
|
||||
import "codit/internal/models"
|
||||
import "codit/internal/util"
|
||||
|
||||
const logIDRPMMirror string = "rpm-mirror"
|
||||
|
||||
type MirrorManager struct {
|
||||
store *db.Store
|
||||
logger *util.Logger
|
||||
logger codit_logger.Logger
|
||||
meta *MetaManager
|
||||
stopCh chan struct{}
|
||||
cancelMu sync.Mutex
|
||||
@@ -93,7 +93,7 @@ type mirrorHTTPConfig struct {
|
||||
DefaultServer string
|
||||
}
|
||||
|
||||
func NewMirrorManager(store *db.Store, logger *util.Logger, meta *MetaManager) *MirrorManager {
|
||||
func NewMirrorManager(store *db.Store, logger codit_logger.Logger, meta *MetaManager) *MirrorManager {
|
||||
var m *MirrorManager
|
||||
m = &MirrorManager{
|
||||
store: store,
|
||||
@@ -131,7 +131,7 @@ func (m *MirrorManager) Start() {
|
||||
}
|
||||
err = m.store.ResetRunningRPMMirrorTasks()
|
||||
if err != nil && m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "reset running tasks failed err=%v", err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "reset running tasks failed err=%v", err)
|
||||
}
|
||||
tasks, err = m.store.ListRPMMirrorPaths()
|
||||
if err == nil {
|
||||
@@ -175,7 +175,7 @@ func (m *MirrorManager) runDue() {
|
||||
tasks, err = m.store.ListDueRPMMirrorTasks(now, 8)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "list due tasks failed err=%v", err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "list due tasks failed err=%v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -183,7 +183,7 @@ func (m *MirrorManager) runDue() {
|
||||
runID, started, err = m.store.TryStartRPMMirrorRun(tasks[i].RepoID, tasks[i].MirrorPath, now)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "try start failed repo=%s path=%s err=%v", tasks[i].RepoID, tasks[i].MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "try start failed repo=%s path=%s err=%v", tasks[i].RepoID, tasks[i].MirrorPath, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -229,20 +229,20 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
cfg, err = buildMirrorHTTPConfig(task)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=start err=%v", task.RepoID, task.MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=start err=%v", task.RepoID, task.MirrorPath, err)
|
||||
}
|
||||
m.finishTaskRun(task, runID, false, "start", 0, 0, 0, 0, "", err.Error())
|
||||
return
|
||||
}
|
||||
client = buildMirrorHTTPClient(cfg)
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_INFO, "sync start repo=%s path=%s remote=%s", task.RepoID, task.MirrorPath, task.RemoteURL)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_INFO, "sync start repo=%s path=%s remote=%s", task.RepoID, task.MirrorPath, task.RemoteURL)
|
||||
}
|
||||
_ = m.store.UpdateRPMMirrorTaskProgress(task.RepoID, task.MirrorPath, "fetch_repodata", 0, 0, 0, 0)
|
||||
repomdData, err = mirrorFetch(syncCtx, client, cfg, "repodata/repomd.xml")
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=fetch_repodata err=%v", task.RepoID, task.MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=fetch_repodata err=%v", task.RepoID, task.MirrorPath, err)
|
||||
}
|
||||
m.finishTaskRun(task, runID, false, "fetch_repodata", 0, 0, 0, 0, "", err.Error())
|
||||
return
|
||||
@@ -253,7 +253,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
ensureRepodata(task, localRoot, m.meta, m.logger)
|
||||
}
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_INFO, "sync done repo=%s path=%s status=no_change revision=%s", task.RepoID, task.MirrorPath, revision)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_INFO, "sync done repo=%s path=%s status=no_change revision=%s", task.RepoID, task.MirrorPath, revision)
|
||||
}
|
||||
m.finishTaskRun(task, runID, true, "no_change", 0, 0, 0, 0, revision, "")
|
||||
return
|
||||
@@ -261,7 +261,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
primaryHref, err = parseRepomdPrimaryHref(repomdData)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=parse_repodata err=%v", task.RepoID, task.MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=parse_repodata err=%v", task.RepoID, task.MirrorPath, err)
|
||||
}
|
||||
m.finishTaskRun(task, runID, false, "fetch_repodata", 0, 0, 0, 0, "", err.Error())
|
||||
return
|
||||
@@ -270,7 +270,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
primaryData, err = mirrorFetch(syncCtx, client, cfg, primaryHref)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=fetch_primary err=%v", task.RepoID, task.MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=fetch_primary err=%v", task.RepoID, task.MirrorPath, err)
|
||||
}
|
||||
m.finishTaskRun(task, runID, false, "fetch_primary", 0, 0, 0, 0, "", err.Error())
|
||||
return
|
||||
@@ -279,7 +279,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
primaryData, err = gunzipBytes(primaryData)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=decode_primary err=%v", task.RepoID, task.MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=decode_primary err=%v", task.RepoID, task.MirrorPath, err)
|
||||
}
|
||||
m.finishTaskRun(task, runID, false, "fetch_primary", 0, 0, 0, 0, "", err.Error())
|
||||
return
|
||||
@@ -288,15 +288,15 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
expected, duplicateCount, err = parsePrimaryPackages(primaryData)
|
||||
if err != nil {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=parse_primary err=%v", task.RepoID, task.MirrorPath, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=parse_primary err=%v", task.RepoID, task.MirrorPath, err)
|
||||
}
|
||||
m.finishTaskRun(task, runID, false, "fetch_primary", 0, 0, 0, 0, "", err.Error())
|
||||
return
|
||||
}
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_INFO, "primary parsed repo=%s path=%s primary_href=%s packages=%d", task.RepoID, task.MirrorPath, primaryHref, len(expected))
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_INFO, "primary parsed repo=%s path=%s primary_href=%s packages=%d", task.RepoID, task.MirrorPath, primaryHref, len(expected))
|
||||
if duplicateCount > 0 {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_WARN, "primary has duplicate package paths repo=%s path=%s primary_href=%s duplicates=%d", task.RepoID, task.MirrorPath, primaryHref, duplicateCount)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_WARN, "primary has duplicate package paths repo=%s path=%s primary_href=%s duplicates=%d", task.RepoID, task.MirrorPath, primaryHref, duplicateCount)
|
||||
}
|
||||
}
|
||||
total, done, failed, deleted, changed, err = m.applyMirror(syncCtx, task, localRoot, client, cfg, expected)
|
||||
@@ -304,9 +304,9 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
canceled = errors.Is(err, context.Canceled)
|
||||
if m.logger != nil {
|
||||
if canceled {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_WARN, "sync canceled repo=%s path=%s step=apply total=%d done=%d failed=%d deleted=%d err=%v", task.RepoID, task.MirrorPath, total, done, failed, deleted, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_WARN, "sync canceled repo=%s path=%s step=apply total=%d done=%d failed=%d deleted=%d err=%v", task.RepoID, task.MirrorPath, total, done, failed, deleted, err)
|
||||
} else {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "sync failed repo=%s path=%s step=apply total=%d done=%d failed=%d deleted=%d err=%v", task.RepoID, task.MirrorPath, total, done, failed, deleted, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "sync failed repo=%s path=%s step=apply total=%d done=%d failed=%d deleted=%d err=%v", task.RepoID, task.MirrorPath, total, done, failed, deleted, err)
|
||||
}
|
||||
}
|
||||
if canceled {
|
||||
@@ -318,14 +318,14 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
||||
}
|
||||
if m.meta != nil && changed > 0 {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_INFO, "repodata schedule repo=%s path=%s reason=sync_changed changed=%d", task.RepoID, task.MirrorPath, changed)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_INFO, "repodata schedule repo=%s path=%s reason=sync_changed changed=%d", task.RepoID, task.MirrorPath, changed)
|
||||
}
|
||||
m.meta.Schedule(localRoot)
|
||||
}
|
||||
m.finishTaskRun(task, runID, true, "done", total, done, failed, deleted, revision, "")
|
||||
_ = m.store.CleanupRPMMirrorRunsRetention(task.RepoID, task.MirrorPath, 200, 30)
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_INFO, "sync done repo=%s path=%s status=success total=%d done=%d failed=%d deleted=%d revision=%s", task.RepoID, task.MirrorPath, total, done, failed, deleted, revision)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_INFO, "sync done repo=%s path=%s status=success total=%d done=%d failed=%d deleted=%d revision=%s", task.RepoID, task.MirrorPath, total, done, failed, deleted, revision)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ func (m *MirrorManager) finishTaskRun(task models.RPMMirrorTask, runID string, s
|
||||
finishedAt = time.Now().UTC().Unix()
|
||||
err = m.store.FinishRPMMirrorTaskRun(task.RepoID, task.MirrorPath, runID, success, finishedAt, step, total, done, failed, deleted, revision, errMsg)
|
||||
if err != nil && m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_ERROR, "finish sync state failed repo=%s path=%s run=%s err=%v", task.RepoID, task.MirrorPath, runID, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "finish sync state failed repo=%s path=%s run=%s err=%v", task.RepoID, task.MirrorPath, runID, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +369,7 @@ func (m *MirrorManager) applyMirror(ctx context.Context, task models.RPMMirrorTa
|
||||
continue
|
||||
}
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_DEBUG, "delete local stale repo=%s path=%s file=%s", task.RepoID, task.MirrorPath, path)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_DEBUG, "delete local stale repo=%s path=%s file=%s", task.RepoID, task.MirrorPath, path)
|
||||
}
|
||||
err = os.Remove(filepath.Join(localRoot, filepath.FromSlash(path)))
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
@@ -377,7 +377,7 @@ func (m *MirrorManager) applyMirror(ctx context.Context, task models.RPMMirrorTa
|
||||
changed = changed + 1
|
||||
} else {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_WARN, "delete local stale failed repo=%s path=%s file=%s err=%v", task.RepoID, task.MirrorPath, path, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_WARN, "delete local stale failed repo=%s path=%s file=%s err=%v", task.RepoID, task.MirrorPath, path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,24 +398,24 @@ func (m *MirrorManager) applyMirror(ctx context.Context, task models.RPMMirrorTa
|
||||
}
|
||||
if needDownload {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_DEBUG, "download start repo=%s path=%s file=%s checksum_type=%s checksum=%s", task.RepoID, task.MirrorPath, path, checksum.Algo, checksum.Value)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_DEBUG, "download start repo=%s path=%s file=%s checksum_type=%s checksum=%s", task.RepoID, task.MirrorPath, path, checksum.Algo, checksum.Value)
|
||||
}
|
||||
err = mirrorDownload(ctx, client, cfg, path, fullPath, checksum.Algo, checksum.Value)
|
||||
if err != nil {
|
||||
failed = failed + 1
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_WARN, "download failed repo=%s path=%s file=%s err=%v", task.RepoID, task.MirrorPath, path, err)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_WARN, "download failed repo=%s path=%s file=%s err=%v", task.RepoID, task.MirrorPath, path, err)
|
||||
}
|
||||
_ = m.store.UpdateRPMMirrorTaskProgress(task.RepoID, task.MirrorPath, "apply", total, done, failed, deleted)
|
||||
continue
|
||||
}
|
||||
changed = changed + 1
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_DEBUG, "download done repo=%s path=%s file=%s", task.RepoID, task.MirrorPath, path)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_DEBUG, "download done repo=%s path=%s file=%s", task.RepoID, task.MirrorPath, path)
|
||||
}
|
||||
} else {
|
||||
if m.logger != nil {
|
||||
m.logger.Write(logIDRPMMirror, util.LOG_DEBUG, "download skip repo=%s path=%s file=%s reason=up-to-date", task.RepoID, task.MirrorPath, path)
|
||||
m.logger.Write(logIDRPMMirror, codit_logger.LOG_DEBUG, "download skip repo=%s path=%s file=%s reason=up-to-date", task.RepoID, task.MirrorPath, path)
|
||||
}
|
||||
}
|
||||
done = done + 1
|
||||
@@ -853,7 +853,7 @@ func mirrorTaskKey(repoID string, path string) string {
|
||||
return repoID + "\x00" + path
|
||||
}
|
||||
|
||||
func ensureRepodata(task models.RPMMirrorTask, localRoot string, meta *MetaManager, logger *util.Logger) {
|
||||
func ensureRepodata(task models.RPMMirrorTask, localRoot string, meta *MetaManager, logger codit_logger.Logger) {
|
||||
var repomdPath string
|
||||
var statErr error
|
||||
repomdPath = filepath.Join(localRoot, "repodata", "repomd.xml")
|
||||
@@ -862,7 +862,7 @@ func ensureRepodata(task models.RPMMirrorTask, localRoot string, meta *MetaManag
|
||||
return
|
||||
}
|
||||
if logger != nil {
|
||||
logger.Write(logIDRPMMirror, util.LOG_INFO, "repodata schedule repo=%s path=%s reason=missing repomd=%s", task.RepoID, task.MirrorPath, repomdPath)
|
||||
logger.Write(logIDRPMMirror, codit_logger.LOG_INFO, "repodata schedule repo=%s path=%s reason=missing repomd=%s", task.RepoID, task.MirrorPath, repomdPath)
|
||||
}
|
||||
meta.Schedule(localRoot)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package codit
|
||||
|
||||
import "io"
|
||||
|
||||
import codit_logger "codit/logger"
|
||||
|
||||
// this public file is to workaround the import-cycle issue.
|
||||
// codit/logger can't import from the root package.
|
||||
|
||||
type LogLevel = codit_logger.LogLevel
|
||||
|
||||
type LogMask = codit_logger.LogMask
|
||||
|
||||
type Logger = codit_logger.Logger
|
||||
|
||||
type AsyncLogger = codit_logger.AsyncLogger
|
||||
|
||||
const LOG_DEBUG LogLevel = codit_logger.LOG_DEBUG
|
||||
const LOG_INFO LogLevel = codit_logger.LOG_INFO
|
||||
const LOG_WARN LogLevel = codit_logger.LOG_WARN
|
||||
const LOG_ERROR LogLevel = codit_logger.LOG_ERROR
|
||||
const LOG_ALL LogMask = codit_logger.LOG_ALL
|
||||
const LOG_NONE LogMask = codit_logger.LOG_NONE
|
||||
|
||||
func NewAsyncLogger(id string, w io.Writer, mask LogMask) *AsyncLogger {
|
||||
return codit_logger.NewAsyncLogger(id, w, mask)
|
||||
}
|
||||
|
||||
func NewAsyncLoggerToFile(id string, file_name string, max_size int64, rotate int, mask LogMask) (*AsyncLogger, error) {
|
||||
return codit_logger.NewAsyncLoggerToFile(id, file_name, max_size, rotate, mask)
|
||||
}
|
||||
|
||||
func LogStrsToMask(str []string) LogMask {
|
||||
return codit_logger.LogStrsToMask(str)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package util
|
||||
package logger
|
||||
|
||||
import "fmt"
|
||||
import "io"
|
||||
@@ -11,8 +11,8 @@ import "sync/atomic"
|
||||
import "syscall"
|
||||
import "time"
|
||||
|
||||
type LogLevel int
|
||||
type LogMask int
|
||||
type LogLevel = int
|
||||
type LogMask = int
|
||||
|
||||
const (
|
||||
LOG_DEBUG LogLevel = 1 << iota
|
||||
@@ -24,12 +24,19 @@ const (
|
||||
const LOG_ALL LogMask = LogMask(LOG_DEBUG | LOG_INFO | LOG_WARN | LOG_ERROR)
|
||||
const LOG_NONE LogMask = LogMask(0)
|
||||
|
||||
type Logger interface {
|
||||
Write(id string, level LogLevel, fmtstr string, args ...interface{})
|
||||
WriteWithCallDepth(id string, level LogLevel, call_depth int, fmtstr string, args ...interface{})
|
||||
Rotate()
|
||||
Close()
|
||||
}
|
||||
|
||||
type logger_msg_t struct {
|
||||
code int
|
||||
data string
|
||||
}
|
||||
|
||||
type Logger struct {
|
||||
type AsyncLogger struct {
|
||||
id string
|
||||
out io.Writer
|
||||
mask LogMask
|
||||
@@ -63,8 +70,8 @@ func _is_ansi_tty(fd uintptr) bool {
|
||||
}
|
||||
|
||||
|
||||
func NewLogger(id string, w io.Writer, mask LogMask) *Logger {
|
||||
var l *Logger
|
||||
func NewAsyncLogger(id string, w io.Writer, mask LogMask) *AsyncLogger {
|
||||
var l *AsyncLogger
|
||||
var f *os.File
|
||||
var ok bool
|
||||
var use_color bool
|
||||
@@ -73,7 +80,7 @@ func NewLogger(id string, w io.Writer, mask LogMask) *Logger {
|
||||
f, ok = w.(*os.File)
|
||||
if ok { use_color = _is_ansi_tty(f.Fd()) }
|
||||
|
||||
l = &Logger{
|
||||
l = &AsyncLogger{
|
||||
id: id,
|
||||
out: w,
|
||||
mask: mask,
|
||||
@@ -86,8 +93,8 @@ func NewLogger(id string, w io.Writer, mask LogMask) *Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
func NewLoggerToFile(id string, file_name string, max_size int64, rotate int, mask LogMask) (*Logger, error) {
|
||||
var l *Logger
|
||||
func NewAsyncLoggerToFile(id string, file_name string, max_size int64, rotate int, mask LogMask) (*AsyncLogger, error) {
|
||||
var l *AsyncLogger
|
||||
var f *os.File
|
||||
var fi os.FileInfo
|
||||
var err error
|
||||
@@ -102,7 +109,7 @@ func NewLoggerToFile(id string, file_name string, max_size int64, rotate int, ma
|
||||
rotate = 0
|
||||
}
|
||||
|
||||
l = &Logger{
|
||||
l = &AsyncLogger{
|
||||
id: id,
|
||||
out: f,
|
||||
mask: mask,
|
||||
@@ -119,7 +126,7 @@ func NewLoggerToFile(id string, file_name string, max_size int64, rotate int, ma
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *Logger) Close() {
|
||||
func (l *AsyncLogger) Close() {
|
||||
if l.closed.CompareAndSwap(false, true) {
|
||||
l.msg_chan <- logger_msg_t{code: 1}
|
||||
l.wg.Wait()
|
||||
@@ -127,11 +134,11 @@ func (l *Logger) Close() {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Rotate() {
|
||||
func (l *AsyncLogger) Rotate() {
|
||||
l.msg_chan <- logger_msg_t{code: 2}
|
||||
}
|
||||
|
||||
func (l *Logger) logger_task() {
|
||||
func (l *AsyncLogger) logger_task() {
|
||||
var msg logger_msg_t
|
||||
defer l.wg.Done()
|
||||
|
||||
@@ -160,17 +167,17 @@ main_loop:
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Write(id string, level LogLevel, fmtstr string, args ...interface{}) {
|
||||
func (l *AsyncLogger) Write(id string, level LogLevel, fmtstr string, args ...interface{}) {
|
||||
if l.mask & LogMask(level) == 0 { return }
|
||||
l.write(id, level, 1, fmtstr, args...)
|
||||
}
|
||||
|
||||
func (l *Logger) WriteWithCallDepth(id string, level LogLevel, call_depth int, fmtstr string, args ...interface{}) {
|
||||
func (l *AsyncLogger) WriteWithCallDepth(id string, level LogLevel, call_depth int, fmtstr string, args ...interface{}) {
|
||||
if l.mask & LogMask(level) == 0 { return }
|
||||
l.write(id, level, call_depth + 1, fmtstr, args...)
|
||||
}
|
||||
|
||||
func (l *Logger) write(id string, level LogLevel, call_depth int, fmtstr string, args ...interface{}) {
|
||||
func (l *AsyncLogger) write(id string, level LogLevel, call_depth int, fmtstr string, args ...interface{}) {
|
||||
var now time.Time
|
||||
var off_m int
|
||||
var off_h int
|
||||
@@ -223,7 +230,7 @@ func (l *Logger) write(id string, level LogLevel, call_depth int, fmtstr string,
|
||||
l.msg_chan <- logger_msg_t{ code: 0, data: sb.String() }
|
||||
}
|
||||
|
||||
func (l *Logger) rotate() {
|
||||
func (l *AsyncLogger) rotate() {
|
||||
var f *os.File
|
||||
var fi os.FileInfo
|
||||
var i int
|
||||
@@ -259,7 +266,7 @@ func (l *Logger) rotate() {
|
||||
}
|
||||
}
|
||||
|
||||
func (l* Logger) log_level_to_ansi_code(level LogLevel) string {
|
||||
func (l* AsyncLogger) log_level_to_ansi_code(level LogLevel) string {
|
||||
switch level {
|
||||
case LOG_ERROR:
|
||||
return "\x1B[31m" // red
|
||||
@@ -0,0 +1,6 @@
|
||||
package codit
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var migrationFiles embed.FS
|
||||
+2177
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,86 @@ The current baseline is a single clean initialization migration. Future schema c
|
||||
- JSON arrays and objects are stored as text columns with names ending in `_json`.
|
||||
- Secrets and private keys are currently stored in database text columns. Treat database backups as sensitive material.
|
||||
|
||||
## Relationship Diagrams
|
||||
|
||||
The diagrams below are intentionally split by domain. They show the main logical relationships; a few relationships are implemented through `public_id` string columns rather than strict integer foreign keys.
|
||||
|
||||
### Identity And Authorization
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ sessions : owns
|
||||
users ||--o{ api_keys : owns
|
||||
users ||--o{ user_group_members : joins
|
||||
user_groups ||--o{ user_group_members : contains
|
||||
service_principals ||--o{ principal_api_keys : owns
|
||||
service_principals ||--o{ cert_principal_bindings : maps
|
||||
service_principals ||--o{ principal_project_roles : assigned
|
||||
users ||..o{ subject_permissions : subject
|
||||
user_groups ||..o{ subject_permissions : subject
|
||||
service_principals ||..o{ subject_permissions : subject
|
||||
```
|
||||
|
||||
### Projects And Repository Content
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ projects : creates
|
||||
users ||--o{ project_members : member
|
||||
projects ||--o{ project_members : has
|
||||
projects ||--o{ project_role_bindings : grants
|
||||
projects ||--o{ repos : owns
|
||||
projects ||--o{ project_repos : attaches
|
||||
repos ||--o{ project_repos : visible_as
|
||||
projects ||--o{ issues : tracks
|
||||
issues ||--o{ issue_comments : has
|
||||
projects ||--o{ wiki_pages : documents
|
||||
projects ||--o{ uploads : stores
|
||||
```
|
||||
|
||||
### PKI And ACME
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
pki_cas ||--o{ pki_cas : parent
|
||||
pki_cas ||--o{ pki_certs : issues
|
||||
pki_cas ||--o{ pki_client_profiles : backs
|
||||
pki_client_profiles ||--o{ pki_client_profile_targets : targets
|
||||
pki_client_profiles ||--o{ pki_client_issuances : records
|
||||
pki_certs ||..o{ pki_client_issuances : cert_snapshot
|
||||
acme_profiles ||--o{ acme_orders : creates
|
||||
pki_certs ||..o{ acme_orders : result_cert
|
||||
```
|
||||
|
||||
### SSH Certificates And Web SSH Broker
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
ssh_user_cas ||--o{ ssh_user_ca_issuances : signs
|
||||
users ||..o{ ssh_user_ca_issuances : issuer
|
||||
ssh_principal_grants ||--o{ ssh_principal_grant_targets : targets
|
||||
ssh_principal_grants ||..o{ ssh_user_ca_issuances : authorizes
|
||||
ssh_servers ||--o{ ssh_server_host_keys : pins
|
||||
ssh_servers ||--o{ ssh_access_profiles : exposes
|
||||
ssh_secrets ||..o{ ssh_access_profiles : credential
|
||||
ssh_user_cas ||..o{ ssh_access_profiles : managed_cert_ca
|
||||
ssh_access_profiles ||--o{ ssh_access_profile_targets : targets
|
||||
ssh_access_profiles ||--o{ ssh_sessions : starts
|
||||
ssh_servers ||--o{ ssh_sessions : target
|
||||
users ||--o{ ssh_sessions : opens
|
||||
```
|
||||
|
||||
### TLS And RPM Mirror State
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
tls_auth_policies ||..o{ tls_listeners : referenced_by
|
||||
pki_certs ||..o{ tls_listeners : server_cert
|
||||
pki_cas ||..o{ tls_listeners : client_ca
|
||||
repos ||--o{ rpm_repo_dirs : contains
|
||||
rpm_repo_dirs ||--o{ rpm_mirror_runs : records
|
||||
```
|
||||
|
||||
## Core Identity And Auth
|
||||
|
||||
### `users`
|
||||
|
||||
Reference in New Issue
Block a user