Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf8dd2e441 | |||
| 4cfecbdf76 | |||
| cf45778de0 | |||
| 930cea4617 | |||
| b80eea5c1f |
+18
-2180
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"`
|
RPMHTTPPrefix string `json:"rpm_http_prefix"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DefaultEnvPrefix string = "CODIT_"
|
||||||
|
|
||||||
|
type Duration time.Duration
|
||||||
|
|
||||||
func Load(path string) (Config, error) {
|
func Load(path string) (Config, error) {
|
||||||
|
return LoadWithEnvPrefix(path, DefaultEnvPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadWithEnvPrefix(path string, envPrefix string) (Config, error) {
|
||||||
var cfg Config
|
var cfg Config
|
||||||
var data []byte
|
var data []byte
|
||||||
var err error
|
var err error
|
||||||
@@ -55,7 +63,7 @@ func Load(path string) (Config, error) {
|
|||||||
DataDir: "./codit-data",
|
DataDir: "./codit-data",
|
||||||
FrontendDir: filepath.Join("..", "frontend", "dist"),
|
FrontendDir: filepath.Join("..", "frontend", "dist"),
|
||||||
DBDriver: "sqlite",
|
DBDriver: "sqlite",
|
||||||
DBDSN: "file:./codit-data/codit.db?_pragma=foreign_keys(1)",
|
DBDSN: "file:./codit-data/codit.db",
|
||||||
SessionTTL: Duration(24 * time.Hour),
|
SessionTTL: Duration(24 * time.Hour),
|
||||||
AuthMode: "db",
|
AuthMode: "db",
|
||||||
LDAPUserFilter: "(uid={username})",
|
LDAPUserFilter: "(uid={username})",
|
||||||
@@ -76,7 +84,7 @@ func Load(path string) (Config, error) {
|
|||||||
return cfg, err
|
return cfg, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override(&cfg)
|
override(&cfg, envPrefix)
|
||||||
cfg.AuthMode = strings.ToLower(strings.TrimSpace(cfg.AuthMode))
|
cfg.AuthMode = strings.ToLower(strings.TrimSpace(cfg.AuthMode))
|
||||||
cfg.TLSServerCertSource = strings.ToLower(strings.TrimSpace(cfg.TLSServerCertSource))
|
cfg.TLSServerCertSource = strings.ToLower(strings.TrimSpace(cfg.TLSServerCertSource))
|
||||||
cfg.TLSClientAuth = strings.ToLower(strings.TrimSpace(cfg.TLSClientAuth))
|
cfg.TLSClientAuth = strings.ToLower(strings.TrimSpace(cfg.TLSClientAuth))
|
||||||
@@ -91,143 +99,147 @@ func Load(path string) (Config, error) {
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func override(cfg *Config) {
|
func override(cfg *Config, envPrefix string) {
|
||||||
var v string
|
var v string
|
||||||
v = os.Getenv("CODIT_HTTP_ADDRS")
|
v = getEnv(envPrefix, "HTTP_ADDRS")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.HTTPAddrs = splitCSV(v)
|
cfg.HTTPAddrs = splitCSV(v)
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_HTTPS_ADDRS")
|
v = getEnv(envPrefix, "HTTPS_ADDRS")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.HTTPSAddrs = splitCSV(v)
|
cfg.HTTPSAddrs = splitCSV(v)
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_PUBLIC_BASE_URL")
|
v = getEnv(envPrefix, "PUBLIC_BASE_URL")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.PublicBaseURL = v
|
cfg.PublicBaseURL = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_DATA_DIR")
|
v = getEnv(envPrefix, "DATA_DIR")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.DataDir = v
|
cfg.DataDir = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_FRONTEND_DIR")
|
v = getEnv(envPrefix, "FRONTEND_DIR")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.FrontendDir = v
|
cfg.FrontendDir = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_DB_DRIVER")
|
v = getEnv(envPrefix, "DB_DRIVER")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.DBDriver = v
|
cfg.DBDriver = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_DB_DSN")
|
v = getEnv(envPrefix, "DB_DSN")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.DBDSN = v
|
cfg.DBDSN = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_AUTH_MODE")
|
v = getEnv(envPrefix, "AUTH_MODE")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.AuthMode = v
|
cfg.AuthMode = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_LDAP_URL")
|
v = getEnv(envPrefix, "LDAP_URL")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.LDAPURL = v
|
cfg.LDAPURL = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_LDAP_BIND_DN")
|
v = getEnv(envPrefix, "LDAP_BIND_DN")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.LDAPBindDN = v
|
cfg.LDAPBindDN = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_LDAP_BIND_PASSWORD")
|
v = getEnv(envPrefix, "LDAP_BIND_PASSWORD")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.LDAPBindPassword = v
|
cfg.LDAPBindPassword = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_LDAP_USER_BASE_DN")
|
v = getEnv(envPrefix, "LDAP_USER_BASE_DN")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.LDAPUserBaseDN = v
|
cfg.LDAPUserBaseDN = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_LDAP_USER_FILTER")
|
v = getEnv(envPrefix, "LDAP_USER_FILTER")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.LDAPUserFilter = v
|
cfg.LDAPUserFilter = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_LDAP_TLS_INSECURE_SKIP_VERIFY")
|
v = getEnv(envPrefix, "LDAP_TLS_INSECURE_SKIP_VERIFY")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.LDAPTLSInsecureSkipVerify = parseEnvBool(v)
|
cfg.LDAPTLSInsecureSkipVerify = parseEnvBool(v)
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_CLIENT_ID")
|
v = getEnv(envPrefix, "OIDC_CLIENT_ID")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCClientID = v
|
cfg.OIDCClientID = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_CLIENT_SECRET")
|
v = getEnv(envPrefix, "OIDC_CLIENT_SECRET")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCClientSecret = v
|
cfg.OIDCClientSecret = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_AUTHORIZE_URL")
|
v = getEnv(envPrefix, "OIDC_AUTHORIZE_URL")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCAuthorizeURL = v
|
cfg.OIDCAuthorizeURL = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_TOKEN_URL")
|
v = getEnv(envPrefix, "OIDC_TOKEN_URL")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCTokenURL = v
|
cfg.OIDCTokenURL = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_USERINFO_URL")
|
v = getEnv(envPrefix, "OIDC_USERINFO_URL")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCUserInfoURL = v
|
cfg.OIDCUserInfoURL = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_REDIRECT_URL")
|
v = getEnv(envPrefix, "OIDC_REDIRECT_URL")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCRedirectURL = v
|
cfg.OIDCRedirectURL = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_SCOPES")
|
v = getEnv(envPrefix, "OIDC_SCOPES")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCScopes = v
|
cfg.OIDCScopes = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_ENABLED")
|
v = getEnv(envPrefix, "OIDC_ENABLED")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCEnabled = parseEnvBool(v)
|
cfg.OIDCEnabled = parseEnvBool(v)
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_OIDC_TLS_INSECURE_SKIP_VERIFY")
|
v = getEnv(envPrefix, "OIDC_TLS_INSECURE_SKIP_VERIFY")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.OIDCTLSInsecureSkipVerify = parseEnvBool(v)
|
cfg.OIDCTLSInsecureSkipVerify = parseEnvBool(v)
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_SERVER_CERT_SOURCE")
|
v = getEnv(envPrefix, "TLS_SERVER_CERT_SOURCE")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSServerCertSource = v
|
cfg.TLSServerCertSource = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_CERT_FILE")
|
v = getEnv(envPrefix, "TLS_CERT_FILE")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSCertFile = v
|
cfg.TLSCertFile = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_KEY_FILE")
|
v = getEnv(envPrefix, "TLS_KEY_FILE")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSKeyFile = v
|
cfg.TLSKeyFile = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_PKI_SERVER_CERT_ID")
|
v = getEnv(envPrefix, "TLS_PKI_SERVER_CERT_ID")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSPKIServerCertID = v
|
cfg.TLSPKIServerCertID = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_CLIENT_AUTH")
|
v = getEnv(envPrefix, "TLS_CLIENT_AUTH")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSClientAuth = v
|
cfg.TLSClientAuth = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_CLIENT_CA_FILE")
|
v = getEnv(envPrefix, "TLS_CLIENT_CA_FILE")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSClientCAFile = v
|
cfg.TLSClientCAFile = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_PKI_CLIENT_CA_ID")
|
v = getEnv(envPrefix, "TLS_PKI_CLIENT_CA_ID")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSPKIClientCAID = v
|
cfg.TLSPKIClientCAID = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_TLS_MIN_VERSION")
|
v = getEnv(envPrefix, "TLS_MIN_VERSION")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.TLSMinVersion = v
|
cfg.TLSMinVersion = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_GIT_HTTP_PREFIX")
|
v = getEnv(envPrefix, "GIT_HTTP_PREFIX")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.GitHTTPPrefix = v
|
cfg.GitHTTPPrefix = v
|
||||||
}
|
}
|
||||||
v = os.Getenv("CODIT_RPM_HTTP_PREFIX")
|
v = getEnv(envPrefix, "RPM_HTTP_PREFIX")
|
||||||
if v != "" {
|
if v != "" {
|
||||||
cfg.RPMHTTPPrefix = 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 {
|
func (d Duration) Duration() time.Duration {
|
||||||
return time.Duration(d)
|
return time.Duration(d)
|
||||||
@@ -5,7 +5,7 @@ import "encoding/base64"
|
|||||||
import "errors"
|
import "errors"
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
import "codit/internal/config"
|
import "codit/config"
|
||||||
import "golang.org/x/crypto/bcrypt"
|
import "golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
func HashPassword(password string) (string, error) {
|
func HashPassword(password string) (string, error) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import "strings"
|
|||||||
import "testing"
|
import "testing"
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
import "codit/internal/config"
|
import "codit/config"
|
||||||
|
|
||||||
func TestHashAndComparePassword(t *testing.T) {
|
func TestHashAndComparePassword(t *testing.T) {
|
||||||
var hash string
|
var hash string
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "strings"
|
|||||||
import "time"
|
import "time"
|
||||||
import "crypto/tls"
|
import "crypto/tls"
|
||||||
|
|
||||||
import "codit/internal/config"
|
import "codit/config"
|
||||||
import "github.com/go-ldap/ldap/v3"
|
import "github.com/go-ldap/ldap/v3"
|
||||||
|
|
||||||
type LDAPUser struct {
|
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 "context"
|
||||||
import "database/sql"
|
import "database/sql"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
import "io/fs"
|
||||||
import "os"
|
import "os"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
import "sort"
|
import "sort"
|
||||||
@@ -239,6 +240,86 @@ func (s *Store) ApplyMigrations(dir string) error {
|
|||||||
return nil
|
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) {
|
func (s *Store) hasCoreSchema() (bool, error) {
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var value int
|
var value int
|
||||||
@@ -340,6 +421,31 @@ func listMigrationFiles(dir string) ([]string, error) {
|
|||||||
return files, nil
|
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 {
|
func migrationVersionFromPath(path string) string {
|
||||||
return strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
|
return strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import "codit/internal/db"
|
|||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
import "codit/internal/util"
|
||||||
|
import codit_logger "codit/logger"
|
||||||
|
|
||||||
type AuthFunc func(username, password string) (bool, error)
|
type AuthFunc func(username, password string) (bool, error)
|
||||||
|
|
||||||
@@ -23,12 +24,12 @@ type HTTPServer struct {
|
|||||||
store *db.Store
|
store *db.Store
|
||||||
baseDir string
|
baseDir string
|
||||||
auth AuthFunc
|
auth AuthFunc
|
||||||
logger *util.Logger
|
logger codit_logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
const logIDDocker string = "docker"
|
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{
|
return &HTTPServer{
|
||||||
store: store,
|
store: store,
|
||||||
baseDir: baseDir,
|
baseDir: baseDir,
|
||||||
@@ -59,7 +60,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !hasLogInfo {
|
if !hasLogInfo {
|
||||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
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)
|
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
|
return
|
||||||
@@ -74,7 +75,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !hasLogInfo {
|
if !hasLogInfo {
|
||||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
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)
|
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
|
return
|
||||||
@@ -88,7 +89,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !hasLogInfo {
|
if !hasLogInfo {
|
||||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
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)
|
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
|
package git
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/util"
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "os"
|
import "os"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
@@ -12,12 +12,12 @@ import "github.com/sosedoff/gitkit"
|
|||||||
type HTTPServer struct {
|
type HTTPServer struct {
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
baseDir string
|
baseDir string
|
||||||
logger *util.Logger
|
logger codit_logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthFunc func(username, password string) (bool, error)
|
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 cfg gitkit.Config
|
||||||
var srv *gitkit.Server
|
var srv *gitkit.Server
|
||||||
cfg = gitkit.Config{
|
cfg = gitkit.Config{
|
||||||
@@ -74,7 +74,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
mtlsInfo = middleware.ClientCertLogFields(r)
|
mtlsInfo = middleware.ClientCertLogFields(r)
|
||||||
s.logger.Write(
|
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)
|
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
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "context"
|
import "context"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
import "crypto/ecdsa"
|
import "crypto/ecdsa"
|
||||||
@@ -21,7 +22,6 @@ import "time"
|
|||||||
import "golang.org/x/crypto/acme"
|
import "golang.org/x/crypto/acme"
|
||||||
|
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type acmeProfileRequest struct {
|
type acmeProfileRequest struct {
|
||||||
Name string `json:"name"`
|
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"})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request"})
|
||||||
return
|
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)
|
item, err = normalizeACMEProfileRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
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.LastError = ""
|
||||||
item, err = api.store(r).CreateACMEProfile(item)
|
item, err = api.store(r).CreateACMEProfile(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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)
|
out = buildACMEProfileSummary(item)
|
||||||
WriteJSON(w, http.StatusCreated, out)
|
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.Enabled = req.Enabled
|
||||||
item, err = api.store(r).UpdateACMEProfile(item)
|
item, err = api.store(r).UpdateACMEProfile(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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)
|
out = buildACMEProfileSummary(item)
|
||||||
WriteJSON(w, http.StatusOK, out)
|
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"])
|
err = api.store(r).DeleteACMEProfile(params["id"])
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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"})
|
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)
|
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)
|
order, err = api.createACMEOrder(r.Context(), prev.ProfileID, cert.CommonName, sans, cert.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
@@ -362,7 +362,7 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
|||||||
var certKeyPEM string
|
var certKeyPEM string
|
||||||
var csrPEM string
|
var csrPEM string
|
||||||
var err error
|
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) == "" {
|
if strings.TrimSpace(profileID) == "" {
|
||||||
return order, errors.New("profile_id is required")
|
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)
|
client, accountKey, profile, err = api.ensureACMEAccount(ctx, profile)
|
||||||
if err != nil {
|
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())
|
_ = api.storeContext(ctx).UpdateACMEProfileLastError(profile.ID, err.Error())
|
||||||
return order, err
|
return order, err
|
||||||
}
|
}
|
||||||
_ = accountKey
|
_ = 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)
|
rawOrder, err = client.AuthorizeOrder(context.Background(), domainIDs)
|
||||||
if err != nil {
|
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())
|
_ = api.storeContext(ctx).UpdateACMEProfileLastError(profile.ID, err.Error())
|
||||||
return order, err
|
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++ {
|
for i = 0; i < len(rawOrder.AuthzURLs); i++ {
|
||||||
authz, err = client.GetAuthorization(context.Background(), rawOrder.AuthzURLs[i])
|
authz, err = client.GetAuthorization(context.Background(), rawOrder.AuthzURLs[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -430,7 +430,7 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
|||||||
DNSValue: txt,
|
DNSValue: txt,
|
||||||
Status: ch.Status,
|
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{
|
order = models.ACMEOrder{
|
||||||
ProfileID: profile.ID,
|
ProfileID: profile.ID,
|
||||||
@@ -447,10 +447,10 @@ func (api *API) createACMEOrder(ctx context.Context, profileID string, commonNam
|
|||||||
}
|
}
|
||||||
order, err = api.storeContext(ctx).CreateACMEOrder(order)
|
order, err = api.storeContext(ctx).CreateACMEOrder(order)
|
||||||
if err != nil {
|
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
|
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, "")
|
_ = api.storeContext(ctx).UpdateACMEProfileLastError(profile.ID, "")
|
||||||
return order, nil
|
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"})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "renew_mode must be override or new_cert"})
|
||||||
return
|
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"])
|
order, err = api.store(r).GetACMEOrder(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
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)
|
client, accountKey, profile, err = api.ensureACMEAccount(r.Context(), profile)
|
||||||
if err != nil {
|
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.Status = "failed"
|
||||||
order.LastError = err.Error()
|
order.LastError = err.Error()
|
||||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
_, _ = 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 {
|
if authz.Status == acme.StatusValid {
|
||||||
order.Challenges[i].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
|
continue
|
||||||
}
|
}
|
||||||
if profile.SolverType == "acme_dns" {
|
if profile.SolverType == "acme_dns" {
|
||||||
err = api.updateACMEDNSRecord(profile, order.Challenges[i])
|
err = api.updateACMEDNSRecord(profile, order.Challenges[i])
|
||||||
if err != nil {
|
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.Status = "failed"
|
||||||
order.LastError = err.Error()
|
order.LastError = err.Error()
|
||||||
order.Challenges[i].Status = "failed"
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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 = &acme.Challenge{Type: "dns-01", URI: order.Challenges[i].ChallengeURL, Token: order.Challenges[i].Token}
|
||||||
challenge, err = client.Accept(context.Background(), challenge)
|
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)
|
authz, err = client.WaitAuthorization(context.Background(), order.Challenges[i].AuthorizationURL)
|
||||||
if err != nil {
|
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.Status = "failed"
|
||||||
order.LastError = err.Error()
|
order.LastError = err.Error()
|
||||||
order.Challenges[i].Status = "failed"
|
order.Challenges[i].Status = "failed"
|
||||||
@@ -582,11 +582,11 @@ func (api *API) FinalizeACMEOrder(w http.ResponseWriter, r *http.Request, params
|
|||||||
break
|
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)
|
certDER, certURL, err = client.CreateOrderCert(context.Background(), order.FinalizeURL, decodeCSRPEM(order.CSRPEM), true)
|
||||||
if err != nil {
|
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.Status = "failed"
|
||||||
order.LastError = err.Error()
|
order.LastError = err.Error()
|
||||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
_, _ = 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.CAID = existing.CAID
|
||||||
cert, err = api.store(r).ReplacePKICert(cert)
|
cert, err = api.store(r).ReplacePKICert(cert)
|
||||||
if err != nil {
|
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.Status = "failed"
|
||||||
order.LastError = err.Error()
|
order.LastError = err.Error()
|
||||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
_, _ = api.store(r).UpdateACMEOrder(order)
|
||||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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) == "" {
|
if strings.TrimSpace(cert.ID) == "" {
|
||||||
cert, err = api.store(r).CreatePKICert(cert)
|
cert, err = api.store(r).CreatePKICert(cert)
|
||||||
if err != nil {
|
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.Status = "failed"
|
||||||
order.LastError = err.Error()
|
order.LastError = err.Error()
|
||||||
_, _ = api.store(r).UpdateACMEOrder(order)
|
_, _ = 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, "")
|
_ = api.store(r).UpdateACMEProfileLastError(profile.ID, "")
|
||||||
_ = certURL
|
_ = 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)
|
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"])
|
err = api.store(r).DeleteACMEOrder(params["id"])
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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"})
|
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import "time"
|
|||||||
import "unicode"
|
import "unicode"
|
||||||
|
|
||||||
import "codit/internal/auth"
|
import "codit/internal/auth"
|
||||||
import "codit/internal/config"
|
import "codit/config"
|
||||||
import "codit/internal/db"
|
import "codit/internal/db"
|
||||||
import "codit/internal/docker"
|
import "codit/internal/docker"
|
||||||
import "codit/internal/git"
|
import "codit/internal/git"
|
||||||
@@ -28,6 +28,7 @@ import "codit/internal/models"
|
|||||||
import "codit/internal/rpm"
|
import "codit/internal/rpm"
|
||||||
import "codit/internal/storage"
|
import "codit/internal/storage"
|
||||||
import "codit/internal/util"
|
import "codit/internal/util"
|
||||||
|
import codit_logger "codit/logger"
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
Cfg config.Config
|
Cfg config.Config
|
||||||
@@ -38,7 +39,7 @@ type API struct {
|
|||||||
RpmMirror *rpm.MirrorManager
|
RpmMirror *rpm.MirrorManager
|
||||||
DockerBase string
|
DockerBase string
|
||||||
Uploads storage.FileStore
|
Uploads storage.FileStore
|
||||||
Logger *util.Logger
|
Logger codit_logger.Logger
|
||||||
SSHSessionRegistry *SSHSessionRegistry
|
SSHSessionRegistry *SSHSessionRegistry
|
||||||
SSHPromptedAuthStore *SSHPromptedAuthStore
|
SSHPromptedAuthStore *SSHPromptedAuthStore
|
||||||
SSHPreparedSessionStore *SSHPreparedSessionStore
|
SSHPreparedSessionStore *SSHPreparedSessionStore
|
||||||
@@ -386,10 +387,10 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ map[string]strin
|
|||||||
|
|
||||||
authCfg, _ = api.effectiveAuthConfig(r.Context())
|
authCfg, _ = api.effectiveAuthConfig(r.Context())
|
||||||
if authCfg.AuthMode == "ldap" || authCfg.AuthMode == "hybrid" {
|
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)
|
ldapUser, err = auth.LDAPAuthenticateContext(r.Context(), authCfg, req.Username, req.Password)
|
||||||
if err == nil {
|
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 {
|
if user.ID != "" && user.Disabled {
|
||||||
WriteJSON(w, http.StatusForbidden, map[string]string{"error": "user disabled"})
|
WriteJSON(w, http.StatusForbidden, map[string]string{"error": "user disabled"})
|
||||||
return
|
return
|
||||||
@@ -413,7 +414,7 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ map[string]strin
|
|||||||
WriteJSON(w, http.StatusOK, user)
|
WriteJSON(w, http.StatusOK, user)
|
||||||
return
|
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"})
|
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())
|
user, ok = middleware.UserFromContext(r.Context())
|
||||||
if ok {
|
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())
|
settings, err = api.getMergedAuthSettings(r.Context())
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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)
|
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"
|
settings.OIDCScopes = "openid profile email"
|
||||||
}
|
}
|
||||||
if ok {
|
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)
|
user.Username, settings.AuthMode, settings.OIDCEnabled, settings.LDAPURL, settings.OIDCAuthorizeURL)
|
||||||
}
|
}
|
||||||
err = api.store(r).SetAuthSettings(settings)
|
err = api.store(r).SetAuthSettings(settings)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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)
|
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
|
cfg.LDAPUserFilter = merged.LDAPUserFilter
|
||||||
err = auth.LDAPTestConnectionContext(r.Context(), cfg)
|
err = auth.LDAPTestConnectionContext(r.Context(), cfg)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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) != "" {
|
if strings.TrimSpace(req.Username) != "" && strings.TrimSpace(req.Password) != "" {
|
||||||
user, err = auth.LDAPAuthenticateContext(r.Context(), cfg, strings.TrimSpace(req.Username), req.Password)
|
user, err = auth.LDAPAuthenticateContext(r.Context(), cfg, strings.TrimSpace(req.Username), req.Password)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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})
|
WriteJSON(w, http.StatusOK, map[string]string{"status": "ok", "user": user.Username})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "context"
|
import "context"
|
||||||
import "crypto/rand"
|
import "crypto/rand"
|
||||||
import "crypto/sha1"
|
import "crypto/sha1"
|
||||||
@@ -16,9 +17,8 @@ import "net/url"
|
|||||||
import "strings"
|
import "strings"
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
import "codit/internal/config"
|
import "codit/config"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type oidcTokenResponse struct {
|
type oidcTokenResponse struct {
|
||||||
AccessToken string `json:"access_token"`
|
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,
|
SameSite: http.SameSiteLaxMode,
|
||||||
})
|
})
|
||||||
authURL = api.buildOIDCAuthorizeURL(cfg, state)
|
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)
|
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)
|
token, err = api.oidcExchangeCode(r.Context(), cfg, code)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
claims, err = api.oidcResolveClaims(r.Context(), cfg, token)
|
claims, err = api.oidcResolveClaims(r.Context(), cfg, token)
|
||||||
if err != nil {
|
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"})
|
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": "oidc claims fetch failed"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err = api.oidcGetOrCreateUser(r.Context(), claims)
|
user, err = api.oidcGetOrCreateUser(r.Context(), claims)
|
||||||
if err != nil {
|
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"})
|
WriteJSON(w, http.StatusUnauthorized, map[string]string{"error": "oidc user mapping failed"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
api.issueSession(w, r, user)
|
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)
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "archive/zip"
|
import "archive/zip"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
import "context"
|
import "context"
|
||||||
@@ -27,7 +28,6 @@ import "time"
|
|||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/pkiutil"
|
import "codit/internal/pkiutil"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type pkiCreateRootRequest struct {
|
type pkiCreateRootRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -1058,7 +1058,7 @@ func (api *API) DownloadPKICertBundle(w http.ResponseWriter, r *http.Request, pa
|
|||||||
chainCount++
|
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)
|
data, err = buildPKIZipBundle(cert.CommonName, cert.CertPEM, cert.KeyPEM, false, caPEMs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "crypto/rand"
|
import "crypto/rand"
|
||||||
import "crypto/rsa"
|
import "crypto/rsa"
|
||||||
import "crypto/x509"
|
import "crypto/x509"
|
||||||
@@ -20,7 +21,6 @@ import "time"
|
|||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/pkiutil"
|
import "codit/internal/pkiutil"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
const logIDPKI string = "pki"
|
const logIDPKI string = "pki"
|
||||||
const pkiClientMinValidSeconds int64 = 60
|
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)
|
item, err = api.store(r).CreatePKIClientProfile(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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))
|
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)
|
existing, err = api.store(r).UpdatePKIClientProfile(existing)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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))
|
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"])
|
err = api.store(r).DeletePKIClientProfile(params["id"])
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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"})
|
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)
|
serialHex = strconv.FormatInt(serial, 16)
|
||||||
certPEM, keyPEM, notBefore, notAfter, err = issuePKIClientCertFromProfile(ca, serial, user, profile, permissions, commonName, sanDNS, sanIPs, sanURI, validSeconds)
|
certPEM, keyPEM, notBefore, notAfter, err = issuePKIClientCertFromProfile(ca, serial, user, profile, permissions, commonName, sanDNS, sanIPs, sanURI, validSeconds)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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{
|
WriteJSON(w, http.StatusCreated, pkiClientIssueResponse{
|
||||||
Issuance: buildPKIClientIssuanceSummary(issuance),
|
Issuance: buildPKIClientIssuanceSummary(issuance),
|
||||||
CertPEM: cert.CertPEM,
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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"})
|
WriteJSON(w, http.StatusOK, map[string]string{"status": "revoked"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "database/sql"
|
import "database/sql"
|
||||||
import "encoding/base64"
|
import "encoding/base64"
|
||||||
import "errors"
|
import "errors"
|
||||||
@@ -19,7 +20,6 @@ import "golang.org/x/net/websocket"
|
|||||||
import "codit/internal/db"
|
import "codit/internal/db"
|
||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
const logIDSSHBroker string = "ssh-broker"
|
const logIDSSHBroker string = "ssh-broker"
|
||||||
type sshServerRequest struct {
|
type sshServerRequest struct {
|
||||||
@@ -122,7 +122,7 @@ const sshSecondFactorNone string = "none"
|
|||||||
const sshSecondFactorPromptedTOTP string = "prompted_totp"
|
const sshSecondFactorPromptedTOTP string = "prompted_totp"
|
||||||
|
|
||||||
func (api *API) logSSHSessionConnectStart(sessionItem models.SSHSession, profile models.SSHAccessProfile, user models.User) {
|
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",
|
"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.ID,
|
||||||
sessionItem.RemoteAddr,
|
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) {
|
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",
|
"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,
|
sessionID,
|
||||||
remoteAddr,
|
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) {
|
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",
|
"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.ID,
|
||||||
sessionItem.RemoteAddr,
|
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) {
|
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",
|
"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.ID,
|
||||||
sessionItem.RemoteAddr,
|
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) {
|
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",
|
"connect failed session=%s requester=%s user=%s profile=%s stage=%s err=%v",
|
||||||
sessionID,
|
sessionID,
|
||||||
remoteAddr,
|
remoteAddr,
|
||||||
@@ -206,7 +206,7 @@ func (api *API) logSSHSessionClosed(sessionItem models.SSHSession, profile model
|
|||||||
if connectedAt > 0 && endedAt >= connectedAt {
|
if connectedAt > 0 && endedAt >= connectedAt {
|
||||||
durationSeconds = 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",
|
"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.ID,
|
||||||
sessionItem.RemoteAddr,
|
sessionItem.RemoteAddr,
|
||||||
@@ -1860,7 +1860,7 @@ event_loop:
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case err = <-controlErrCh:
|
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",
|
"workspace stream closed requester=%s user=%s err=%v",
|
||||||
remoteAddr,
|
remoteAddr,
|
||||||
user.Username,
|
user.Username,
|
||||||
@@ -1920,7 +1920,7 @@ event_loop:
|
|||||||
InputErrCh: make(chan error, 1),
|
InputErrCh: make(chan error, 1),
|
||||||
}
|
}
|
||||||
attachments[msg.SessionID] = attachment
|
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",
|
"workspace attach session=%s requester=%s user=%s",
|
||||||
msg.SessionID,
|
msg.SessionID,
|
||||||
remoteAddr,
|
remoteAddr,
|
||||||
@@ -2172,7 +2172,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
|||||||
}
|
}
|
||||||
transcriptRecorder, err = api.openSSHSessionTranscriptRecorder(sessionItem.ID)
|
transcriptRecorder, err = api.openSSHSessionTranscriptRecorder(sessionItem.ID)
|
||||||
if err != nil {
|
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",
|
"transcript open failed session=%s err=%v",
|
||||||
sessionItem.ID,
|
sessionItem.ID,
|
||||||
err)
|
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",
|
"session loop ended session=%s requester=%s user=%s profile=%s profile_name=%q source=%s wait_err=%v",
|
||||||
sessionItem.ID,
|
sessionItem.ID,
|
||||||
sessionItem.RemoteAddr,
|
sessionItem.RemoteAddr,
|
||||||
@@ -2247,7 +2247,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
|||||||
}
|
}
|
||||||
if waitErr != nil && !isSSHSessionTerminalExit(waitErr) {
|
if waitErr != nil && !isSSHSessionTerminalExit(waitErr) {
|
||||||
_ = store.UpdateSSHSessionStatus(sessionItem.ID, "error", connectedFingerprint, connectedAt, now, waitErr.Error())
|
_ = 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",
|
"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.ID,
|
||||||
sessionItem.RemoteAddr,
|
sessionItem.RemoteAddr,
|
||||||
@@ -2268,7 +2268,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user models.User, sessionIt
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if isSSHSessionTerminalExit(waitErr) {
|
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",
|
"session ended session=%s requester=%s user=%s profile=%s profile_name=%q err=%v",
|
||||||
sessionItem.ID,
|
sessionItem.ID,
|
||||||
sessionItem.RemoteAddr,
|
sessionItem.RemoteAddr,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "database/sql"
|
import "database/sql"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "io"
|
import "io"
|
||||||
@@ -11,7 +12,6 @@ import "sync"
|
|||||||
|
|
||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type sshSessionTranscriptRecorder struct {
|
type sshSessionTranscriptRecorder struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
@@ -201,7 +201,7 @@ func (api *API) writeSSHSessionTranscriptChunk(sessionID string, data []byte, re
|
|||||||
}
|
}
|
||||||
err = recorder.Write(data)
|
err = recorder.Write(data)
|
||||||
if err != nil {
|
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",
|
"transcript write failed session=%s err=%v",
|
||||||
sessionID,
|
sessionID,
|
||||||
err)
|
err)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "database/sql"
|
import "database/sql"
|
||||||
import "errors"
|
import "errors"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
@@ -8,7 +9,6 @@ import "time"
|
|||||||
|
|
||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type sshPrincipalGrantTargetRequest struct {
|
type sshPrincipalGrantTargetRequest struct {
|
||||||
TargetType string `json:"target_type"`
|
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)
|
item, err = api.store(r).CreateSSHPrincipalGrant(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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))
|
WriteJSON(w, http.StatusCreated, buildSSHPrincipalGrantSummary(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,11 +256,11 @@ func (api *API) UpdateSSHPrincipalGrant(w http.ResponseWriter, r *http.Request,
|
|||||||
item.Targets = targets
|
item.Targets = targets
|
||||||
item, err = api.store(r).UpdateSSHPrincipalGrant(item)
|
item, err = api.store(r).UpdateSSHPrincipalGrant(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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))
|
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"])
|
err = api.store(r).DeleteSSHPrincipalGrant(params["id"])
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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"})
|
WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "crypto/ed25519"
|
import "crypto/ed25519"
|
||||||
import "crypto/ecdsa"
|
import "crypto/ecdsa"
|
||||||
import "crypto/elliptic"
|
import "crypto/elliptic"
|
||||||
@@ -22,7 +23,6 @@ import "golang.org/x/crypto/ssh"
|
|||||||
|
|
||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type sshUserCACreateRequest struct {
|
type sshUserCACreateRequest struct {
|
||||||
Name string `json:"name"`
|
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)
|
item, err = api.store(r).CreateSSHUserCA(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
summary = buildSSHUserCASummary(item)
|
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)
|
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.MaxUserValidSeconds = maxUserValidSeconds
|
||||||
item, err = api.store(r).UpdateSSHUserCA(item)
|
item, err = api.store(r).UpdateSSHUserCA(item)
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
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))
|
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"])
|
err = api.store(r).DeleteSSHUserCA(params["id"])
|
||||||
if err != nil {
|
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()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
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"})
|
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)
|
err = api.recordSSHUserCAIssuance(r, item, user, "admin", sourcePublicKey, sourcePublicKeyFingerprint, nil, nil, response)
|
||||||
if err != nil {
|
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"})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to record issuance audit"})
|
||||||
return
|
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)
|
WriteJSON(w, http.StatusOK, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,18 +720,18 @@ func (api *API) SignSSHUserKeyForSelf(w http.ResponseWriter, r *http.Request, pa
|
|||||||
for grantID = range selectedGrantIDs {
|
for grantID = range selectedGrantIDs {
|
||||||
err = api.store(r).MarkSSHPrincipalGrantUsed(grantID)
|
err = api.store(r).MarkSSHPrincipalGrantUsed(grantID)
|
||||||
if err != nil {
|
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"})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "selected principal grant is not active"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = api.recordSSHUserCAIssuance(r, item, user, "self", sourcePublicKey, sourcePublicKeyFingerprint, selectedIDs, selectedGrantNames, response)
|
err = api.recordSSHUserCAIssuance(r, item, user, "self", sourcePublicKey, sourcePublicKeyFingerprint, selectedIDs, selectedGrantNames, response)
|
||||||
if err != nil {
|
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"})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to record issuance audit"})
|
||||||
return
|
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)
|
WriteJSON(w, http.StatusOK, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "bufio"
|
import "bufio"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "io"
|
import "io"
|
||||||
@@ -8,7 +9,6 @@ import "net/http"
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
type statusRecorder struct {
|
type statusRecorder struct {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
@@ -75,7 +75,7 @@ func (r *statusRecorder) ReadFrom(src io.Reader) (int64, error) {
|
|||||||
return io.Copy(r.ResponseWriter, src)
|
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) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
var recorder *statusRecorder
|
var recorder *statusRecorder
|
||||||
var start time.Time
|
var start time.Time
|
||||||
@@ -104,7 +104,7 @@ func AccessLog(logger *util.Logger, next http.Handler) http.Handler {
|
|||||||
if !ok || authReason == "" {
|
if !ok || authReason == "" {
|
||||||
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)
|
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
|
package middleware
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
import "context"
|
import "context"
|
||||||
|
import "fmt"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "net/http/httptest"
|
import "net/http/httptest"
|
||||||
import "strings"
|
import "strings"
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
import "codit/internal/models"
|
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) {
|
func TestAccessLogWritesRecord(t *testing.T) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
var logger *util.Logger
|
var logger codit_logger.Logger
|
||||||
var handler http.Handler
|
var handler http.Handler
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var recorder *httptest.ResponseRecorder
|
var recorder *httptest.ResponseRecorder
|
||||||
var user models.User
|
var user models.User
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
logger = util.NewLogger("test", &buf, util.LOG_ALL)
|
logger = &testLogger{buf: &buf}
|
||||||
defer logger.Close()
|
defer logger.Close()
|
||||||
handler = AccessLog(logger, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler = AccessLog(logger, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusCreated)
|
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-Methods", "*")
|
||||||
h.Add("Access-Control-Allow-Origin", "*")
|
h.Add("Access-Control-Allow-Origin", "*")
|
||||||
|
|
||||||
if r.Method == "OPTIONS" {
|
if r.Method == http.MethodOptions {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
package rpm
|
package rpm
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "codit/internal/middleware"
|
import "codit/internal/middleware"
|
||||||
import "codit/internal/util"
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|
||||||
type HTTPServer struct {
|
type HTTPServer struct {
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
auth AuthFunc
|
auth AuthFunc
|
||||||
logger *util.Logger
|
logger codit_logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthFunc func(username, password string) (bool, error)
|
type AuthFunc func(username, password string) (bool, error)
|
||||||
|
|
||||||
const logIDRPM string = "rpm"
|
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
|
var server HTTPServer
|
||||||
server = HTTPServer{
|
server = HTTPServer{
|
||||||
handler: http.FileServer(http.Dir(baseDir)),
|
handler: http.FileServer(http.Dir(baseDir)),
|
||||||
@@ -47,7 +47,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !hasLogInfo {
|
if !hasLogInfo {
|
||||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
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
|
return
|
||||||
}
|
}
|
||||||
allowed, err = s.auth(username, password)
|
allowed, err = s.auth(username, password)
|
||||||
@@ -59,7 +59,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !hasLogInfo {
|
if !hasLogInfo {
|
||||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
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
|
return
|
||||||
}
|
}
|
||||||
userLabel = username
|
userLabel = username
|
||||||
@@ -69,7 +69,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !hasLogInfo {
|
if !hasLogInfo {
|
||||||
logInfo = RequestLogInfo{OrgPath: "-", ProjectID: "-", ProjectSlug: "-", RepoID: "-", RepoName: "-"}
|
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 {
|
type statusRecorder struct {
|
||||||
|
|||||||
@@ -1,22 +1,35 @@
|
|||||||
package rpm
|
package rpm
|
||||||
|
|
||||||
import "bytes"
|
import codit_logger "codit/logger"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "net/http/httptest"
|
import "net/http/httptest"
|
||||||
import "os"
|
import "os"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
import "testing"
|
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) {
|
func TestHTTPServerUnauthorizedWithoutBasicAuth(t *testing.T) {
|
||||||
var dir string
|
var dir string
|
||||||
var logger *util.Logger
|
var logger codit_logger.Logger
|
||||||
var server *HTTPServer
|
var server *HTTPServer
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var recorder *httptest.ResponseRecorder
|
var recorder *httptest.ResponseRecorder
|
||||||
dir = t.TempDir()
|
dir = t.TempDir()
|
||||||
logger = util.NewLogger("test", &bytes.Buffer{}, util.LOG_ALL)
|
logger = &testLogger{}
|
||||||
defer logger.Close()
|
defer logger.Close()
|
||||||
server = NewHTTPServer(dir, func(username, password string) (bool, error) {
|
server = NewHTTPServer(dir, func(username, password string) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
@@ -31,7 +44,7 @@ func TestHTTPServerUnauthorizedWithoutBasicAuth(t *testing.T) {
|
|||||||
|
|
||||||
func TestHTTPServerAuthorized(t *testing.T) {
|
func TestHTTPServerAuthorized(t *testing.T) {
|
||||||
var dir string
|
var dir string
|
||||||
var logger *util.Logger
|
var logger codit_logger.Logger
|
||||||
var server *HTTPServer
|
var server *HTTPServer
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var recorder *httptest.ResponseRecorder
|
var recorder *httptest.ResponseRecorder
|
||||||
@@ -39,7 +52,7 @@ func TestHTTPServerAuthorized(t *testing.T) {
|
|||||||
dir = t.TempDir()
|
dir = t.TempDir()
|
||||||
path = filepath.Join(dir, "a.txt")
|
path = filepath.Join(dir, "a.txt")
|
||||||
_ = os.WriteFile(path, []byte("ok"), 0o644)
|
_ = os.WriteFile(path, []byte("ok"), 0o644)
|
||||||
logger = util.NewLogger("test", &bytes.Buffer{}, util.LOG_ALL)
|
logger = &testLogger{}
|
||||||
defer logger.Close()
|
defer logger.Close()
|
||||||
server = NewHTTPServer(dir, func(username, password string) (bool, error) {
|
server = NewHTTPServer(dir, func(username, password string) (bool, error) {
|
||||||
return username == "u" && password == "p", nil
|
return username == "u" && password == "p", nil
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package rpm
|
package rpm
|
||||||
|
|
||||||
|
import codit_logger "codit/logger"
|
||||||
import "compress/gzip"
|
import "compress/gzip"
|
||||||
import "context"
|
import "context"
|
||||||
import "crypto/md5"
|
import "crypto/md5"
|
||||||
@@ -26,13 +27,12 @@ import "time"
|
|||||||
|
|
||||||
import "codit/internal/db"
|
import "codit/internal/db"
|
||||||
import "codit/internal/models"
|
import "codit/internal/models"
|
||||||
import "codit/internal/util"
|
|
||||||
|
|
||||||
const logIDRPMMirror string = "rpm-mirror"
|
const logIDRPMMirror string = "rpm-mirror"
|
||||||
|
|
||||||
type MirrorManager struct {
|
type MirrorManager struct {
|
||||||
store *db.Store
|
store *db.Store
|
||||||
logger *util.Logger
|
logger codit_logger.Logger
|
||||||
meta *MetaManager
|
meta *MetaManager
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
cancelMu sync.Mutex
|
cancelMu sync.Mutex
|
||||||
@@ -93,7 +93,7 @@ type mirrorHTTPConfig struct {
|
|||||||
DefaultServer string
|
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
|
var m *MirrorManager
|
||||||
m = &MirrorManager{
|
m = &MirrorManager{
|
||||||
store: store,
|
store: store,
|
||||||
@@ -131,7 +131,7 @@ func (m *MirrorManager) Start() {
|
|||||||
}
|
}
|
||||||
err = m.store.ResetRunningRPMMirrorTasks()
|
err = m.store.ResetRunningRPMMirrorTasks()
|
||||||
if err != nil && m.logger != nil {
|
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()
|
tasks, err = m.store.ListRPMMirrorPaths()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -175,7 +175,7 @@ func (m *MirrorManager) runDue() {
|
|||||||
tasks, err = m.store.ListDueRPMMirrorTasks(now, 8)
|
tasks, err = m.store.ListDueRPMMirrorTasks(now, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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
|
return
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ func (m *MirrorManager) runDue() {
|
|||||||
runID, started, err = m.store.TryStartRPMMirrorRun(tasks[i].RepoID, tasks[i].MirrorPath, now)
|
runID, started, err = m.store.TryStartRPMMirrorRun(tasks[i].RepoID, tasks[i].MirrorPath, now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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
|
continue
|
||||||
}
|
}
|
||||||
@@ -229,20 +229,20 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
cfg, err = buildMirrorHTTPConfig(task)
|
cfg, err = buildMirrorHTTPConfig(task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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())
|
m.finishTaskRun(task, runID, false, "start", 0, 0, 0, 0, "", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
client = buildMirrorHTTPClient(cfg)
|
client = buildMirrorHTTPClient(cfg)
|
||||||
if m.logger != nil {
|
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)
|
_ = m.store.UpdateRPMMirrorTaskProgress(task.RepoID, task.MirrorPath, "fetch_repodata", 0, 0, 0, 0)
|
||||||
repomdData, err = mirrorFetch(syncCtx, client, cfg, "repodata/repomd.xml")
|
repomdData, err = mirrorFetch(syncCtx, client, cfg, "repodata/repomd.xml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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())
|
m.finishTaskRun(task, runID, false, "fetch_repodata", 0, 0, 0, 0, "", err.Error())
|
||||||
return
|
return
|
||||||
@@ -253,7 +253,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
ensureRepodata(task, localRoot, m.meta, m.logger)
|
ensureRepodata(task, localRoot, m.meta, m.logger)
|
||||||
}
|
}
|
||||||
if m.logger != nil {
|
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, "")
|
m.finishTaskRun(task, runID, true, "no_change", 0, 0, 0, 0, revision, "")
|
||||||
return
|
return
|
||||||
@@ -261,7 +261,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
primaryHref, err = parseRepomdPrimaryHref(repomdData)
|
primaryHref, err = parseRepomdPrimaryHref(repomdData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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())
|
m.finishTaskRun(task, runID, false, "fetch_repodata", 0, 0, 0, 0, "", err.Error())
|
||||||
return
|
return
|
||||||
@@ -270,7 +270,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
primaryData, err = mirrorFetch(syncCtx, client, cfg, primaryHref)
|
primaryData, err = mirrorFetch(syncCtx, client, cfg, primaryHref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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())
|
m.finishTaskRun(task, runID, false, "fetch_primary", 0, 0, 0, 0, "", err.Error())
|
||||||
return
|
return
|
||||||
@@ -279,7 +279,7 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
primaryData, err = gunzipBytes(primaryData)
|
primaryData, err = gunzipBytes(primaryData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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())
|
m.finishTaskRun(task, runID, false, "fetch_primary", 0, 0, 0, 0, "", err.Error())
|
||||||
return
|
return
|
||||||
@@ -288,15 +288,15 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
expected, duplicateCount, err = parsePrimaryPackages(primaryData)
|
expected, duplicateCount, err = parsePrimaryPackages(primaryData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if m.logger != 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())
|
m.finishTaskRun(task, runID, false, "fetch_primary", 0, 0, 0, 0, "", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if m.logger != nil {
|
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 {
|
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)
|
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)
|
canceled = errors.Is(err, context.Canceled)
|
||||||
if m.logger != nil {
|
if m.logger != nil {
|
||||||
if canceled {
|
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 {
|
} 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 {
|
if canceled {
|
||||||
@@ -318,14 +318,14 @@ func (m *MirrorManager) syncOne(task models.RPMMirrorTask, runID string) {
|
|||||||
}
|
}
|
||||||
if m.meta != nil && changed > 0 {
|
if m.meta != nil && changed > 0 {
|
||||||
if m.logger != nil {
|
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.meta.Schedule(localRoot)
|
||||||
}
|
}
|
||||||
m.finishTaskRun(task, runID, true, "done", total, done, failed, deleted, revision, "")
|
m.finishTaskRun(task, runID, true, "done", total, done, failed, deleted, revision, "")
|
||||||
_ = m.store.CleanupRPMMirrorRunsRetention(task.RepoID, task.MirrorPath, 200, 30)
|
_ = m.store.CleanupRPMMirrorRunsRetention(task.RepoID, task.MirrorPath, 200, 30)
|
||||||
if m.logger != nil {
|
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()
|
finishedAt = time.Now().UTC().Unix()
|
||||||
err = m.store.FinishRPMMirrorTaskRun(task.RepoID, task.MirrorPath, runID, success, finishedAt, step, total, done, failed, deleted, revision, errMsg)
|
err = m.store.FinishRPMMirrorTaskRun(task.RepoID, task.MirrorPath, runID, success, finishedAt, step, total, done, failed, deleted, revision, errMsg)
|
||||||
if err != nil && m.logger != nil {
|
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
|
continue
|
||||||
}
|
}
|
||||||
if m.logger != nil {
|
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)))
|
err = os.Remove(filepath.Join(localRoot, filepath.FromSlash(path)))
|
||||||
if err == nil || os.IsNotExist(err) {
|
if err == nil || os.IsNotExist(err) {
|
||||||
@@ -377,7 +377,7 @@ func (m *MirrorManager) applyMirror(ctx context.Context, task models.RPMMirrorTa
|
|||||||
changed = changed + 1
|
changed = changed + 1
|
||||||
} else {
|
} else {
|
||||||
if m.logger != nil {
|
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 needDownload {
|
||||||
if m.logger != nil {
|
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)
|
err = mirrorDownload(ctx, client, cfg, path, fullPath, checksum.Algo, checksum.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failed = failed + 1
|
failed = failed + 1
|
||||||
if m.logger != nil {
|
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)
|
_ = m.store.UpdateRPMMirrorTaskProgress(task.RepoID, task.MirrorPath, "apply", total, done, failed, deleted)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
changed = changed + 1
|
changed = changed + 1
|
||||||
if m.logger != nil {
|
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 {
|
} else {
|
||||||
if m.logger != nil {
|
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
|
done = done + 1
|
||||||
@@ -853,7 +853,7 @@ func mirrorTaskKey(repoID string, path string) string {
|
|||||||
return repoID + "\x00" + path
|
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 repomdPath string
|
||||||
var statErr error
|
var statErr error
|
||||||
repomdPath = filepath.Join(localRoot, "repodata", "repomd.xml")
|
repomdPath = filepath.Join(localRoot, "repodata", "repomd.xml")
|
||||||
@@ -862,7 +862,7 @@ func ensureRepodata(task models.RPMMirrorTask, localRoot string, meta *MetaManag
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if logger != nil {
|
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)
|
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 "fmt"
|
||||||
import "io"
|
import "io"
|
||||||
@@ -11,8 +11,8 @@ import "sync/atomic"
|
|||||||
import "syscall"
|
import "syscall"
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type LogLevel int
|
type LogLevel = int
|
||||||
type LogMask int
|
type LogMask = int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LOG_DEBUG LogLevel = 1 << iota
|
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_ALL LogMask = LogMask(LOG_DEBUG | LOG_INFO | LOG_WARN | LOG_ERROR)
|
||||||
const LOG_NONE LogMask = LogMask(0)
|
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 {
|
type logger_msg_t struct {
|
||||||
code int
|
code int
|
||||||
data string
|
data string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Logger struct {
|
type AsyncLogger struct {
|
||||||
id string
|
id string
|
||||||
out io.Writer
|
out io.Writer
|
||||||
mask LogMask
|
mask LogMask
|
||||||
@@ -63,8 +70,8 @@ func _is_ansi_tty(fd uintptr) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func NewLogger(id string, w io.Writer, mask LogMask) *Logger {
|
func NewAsyncLogger(id string, w io.Writer, mask LogMask) *AsyncLogger {
|
||||||
var l *Logger
|
var l *AsyncLogger
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var ok bool
|
var ok bool
|
||||||
var use_color bool
|
var use_color bool
|
||||||
@@ -73,7 +80,7 @@ func NewLogger(id string, w io.Writer, mask LogMask) *Logger {
|
|||||||
f, ok = w.(*os.File)
|
f, ok = w.(*os.File)
|
||||||
if ok { use_color = _is_ansi_tty(f.Fd()) }
|
if ok { use_color = _is_ansi_tty(f.Fd()) }
|
||||||
|
|
||||||
l = &Logger{
|
l = &AsyncLogger{
|
||||||
id: id,
|
id: id,
|
||||||
out: w,
|
out: w,
|
||||||
mask: mask,
|
mask: mask,
|
||||||
@@ -86,8 +93,8 @@ func NewLogger(id string, w io.Writer, mask LogMask) *Logger {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLoggerToFile(id string, file_name string, max_size int64, rotate int, mask LogMask) (*Logger, error) {
|
func NewAsyncLoggerToFile(id string, file_name string, max_size int64, rotate int, mask LogMask) (*AsyncLogger, error) {
|
||||||
var l *Logger
|
var l *AsyncLogger
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var fi os.FileInfo
|
var fi os.FileInfo
|
||||||
var err error
|
var err error
|
||||||
@@ -102,7 +109,7 @@ func NewLoggerToFile(id string, file_name string, max_size int64, rotate int, ma
|
|||||||
rotate = 0
|
rotate = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
l = &Logger{
|
l = &AsyncLogger{
|
||||||
id: id,
|
id: id,
|
||||||
out: f,
|
out: f,
|
||||||
mask: mask,
|
mask: mask,
|
||||||
@@ -119,7 +126,7 @@ func NewLoggerToFile(id string, file_name string, max_size int64, rotate int, ma
|
|||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) Close() {
|
func (l *AsyncLogger) Close() {
|
||||||
if l.closed.CompareAndSwap(false, true) {
|
if l.closed.CompareAndSwap(false, true) {
|
||||||
l.msg_chan <- logger_msg_t{code: 1}
|
l.msg_chan <- logger_msg_t{code: 1}
|
||||||
l.wg.Wait()
|
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}
|
l.msg_chan <- logger_msg_t{code: 2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) logger_task() {
|
func (l *AsyncLogger) logger_task() {
|
||||||
var msg logger_msg_t
|
var msg logger_msg_t
|
||||||
defer l.wg.Done()
|
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 }
|
if l.mask & LogMask(level) == 0 { return }
|
||||||
l.write(id, level, 1, fmtstr, args...)
|
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 }
|
if l.mask & LogMask(level) == 0 { return }
|
||||||
l.write(id, level, call_depth + 1, fmtstr, args...)
|
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 now time.Time
|
||||||
var off_m int
|
var off_m int
|
||||||
var off_h 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() }
|
l.msg_chan <- logger_msg_t{ code: 0, data: sb.String() }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) rotate() {
|
func (l *AsyncLogger) rotate() {
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var fi os.FileInfo
|
var fi os.FileInfo
|
||||||
var i int
|
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 {
|
switch level {
|
||||||
case LOG_ERROR:
|
case LOG_ERROR:
|
||||||
return "\x1B[31m" // red
|
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`.
|
- 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.
|
- 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
|
## Core Identity And Auth
|
||||||
|
|
||||||
### `users`
|
### `users`
|
||||||
|
|||||||
Reference in New Issue
Block a user