diff options
| author | Clément Michaud <clement.michaud34@gmail.com> | 2020-03-09 20:57:53 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-09 20:57:53 +0100 | 
| commit | c429488738ae97b29794cf589d41c93037d3f7f2 (patch) | |
| tree | fac4fb09db8d3054f3a540af52765d182e3b37fc | |
| parent | 6af27cb3f957df1dad5bfeca34baa963d7318284 (diff) | |
[FEATURE] [BREAKING] Support writing logs in a file. (#686)
* [FEATURE] Support writing logs in a file.
* Add documentation about logs file path.
* Rename logs_level and logs_file_path into log_level and log_file_path.
* Update BREAKING.md
Fixes #338
Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
27 files changed, 108 insertions, 40 deletions
diff --git a/BREAKING.md b/BREAKING.md index e11d3b9e2..bc341323b 100644 --- a/BREAKING.md +++ b/BREAKING.md @@ -6,6 +6,10 @@ recommended not to use the 'latest' Docker image tag blindly but pick a version  and read this documentation before upgrading. This is where you will get information about  breaking changes and about what you should do to overcome those changes. +## Breaking in v4.7.0 + +`logs_level` configuration key has been renamed to `log_level`. +  ## Breaking in v4.0.0  Authelia has been rewritten in Go for better code maintainability and for performance and diff --git a/cmd/authelia/main.go b/cmd/authelia/main.go index 5dd849458..2ed6592a8 100644 --- a/cmd/authelia/main.go +++ b/cmd/authelia/main.go @@ -29,10 +29,6 @@ func startServer() {  		log.Fatal(errors.New("No config file path provided"))  	} -	if os.Getenv("ENVIRONMENT") == "dev" { -		logging.Logger().Info("===> Authelia is running in development mode. <===") -	} -  	config, errs := configuration.Read(configPathFlag)  	if len(errs) > 0 { @@ -42,7 +38,11 @@ func startServer() {  		panic(errors.New("Some errors have been reported"))  	} -	switch config.LogsLevel { +	if err := logging.InitializeLogger(config.LogFilePath); err != nil { +		log.Fatalf("Cannot initialize logger: %v", err) +	} + +	switch config.LogLevel {  	case "info":  		logging.Logger().Info("Logging severity set to info")  		logging.SetLevel(logrus.InfoLevel) @@ -56,6 +56,10 @@ func startServer() {  		logging.SetLevel(logrus.TraceLevel)  	} +	if os.Getenv("ENVIRONMENT") == "dev" { +		logging.Logger().Info("===> Authelia is running in development mode. <===") +	} +  	var userProvider authentication.UserProvider  	if config.AuthenticationBackend.File != nil { diff --git a/config.template.yml b/config.template.yml index 6cdb1c5d5..dd063f53c 100644 --- a/config.template.yml +++ b/config.template.yml @@ -9,7 +9,9 @@ port: 9091  # tls_cert: /var/lib/authelia/ssl/cert.pem  # Level of verbosity for logs: info, debug, trace -logs_level: debug +log_level: debug +## File path where the logs will be written. If not set logs are written to stdout. +# log_file_path: /var/log/authelia  # The secret used to generate JWT tokens when validating user identity by  # email confirmation. diff --git a/docs/configuration/miscellaneous.md b/docs/configuration/miscellaneous.md index 246a55c42..824313b60 100644 --- a/docs/configuration/miscellaneous.md +++ b/docs/configuration/miscellaneous.md @@ -29,14 +29,25 @@ following configuration options:      tls_cert: /var/lib/authelia/ssl/cert.pem -## Logs level +## Log + +### Log level  `optional: true`  Defines the level of logs used by Authelia. This level can be set to  `trace`, `debug`, `info`. -    logs_level: debug +    log_level: debug + +### Log file path + +`optional: true` + +Logs can be stored in a file when file path is provided. Otherwise logs +are written to standard output. + +    log_file_path: /var/log/authelia.log  ## JWT Secret diff --git a/internal/configuration/reader_test.go b/internal/configuration/reader_test.go index 5e455e611..92e0ce9ec 100644 --- a/internal/configuration/reader_test.go +++ b/internal/configuration/reader_test.go @@ -23,7 +23,7 @@ func TestShouldParseConfigFile(t *testing.T) {  	require.Len(t, errors, 0)  	assert.Equal(t, 9091, config.Port) -	assert.Equal(t, "debug", config.LogsLevel) +	assert.Equal(t, "debug", config.LogLevel)  	assert.Equal(t, "https://home.example.com:8080/", config.DefaultRedirectionURL)  	assert.Equal(t, "authelia.com", config.TOTP.Issuer)  	assert.Equal(t, "secret_from_env", config.JWTSecret) diff --git a/internal/configuration/schema/configuration.go b/internal/configuration/schema/configuration.go index d7c518cac..f4178ca7e 100644 --- a/internal/configuration/schema/configuration.go +++ b/internal/configuration/schema/configuration.go @@ -7,7 +7,8 @@ type Configuration struct {  	TLSCert string `mapstructure:"tls_cert"`  	TLSKey  string `mapstructure:"tls_key"` -	LogsLevel string `mapstructure:"logs_level"` +	LogLevel    string `mapstructure:"log_level"` +	LogFilePath string `mapstructure:"log_file_path"`  	// This secret is used by the identity validation process to forge JWT tokens  	// representing the permission to proceed with the operation. diff --git a/internal/configuration/test_resources/config.yml b/internal/configuration/test_resources/config.yml index 8bedc2845..833cadd15 100644 --- a/internal/configuration/test_resources/config.yml +++ b/internal/configuration/test_resources/config.yml @@ -5,7 +5,7 @@  host: 127.0.0.1  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/  totp: diff --git a/internal/configuration/validator/configuration.go b/internal/configuration/validator/configuration.go index 2e9934bcf..890b2bdc6 100644 --- a/internal/configuration/validator/configuration.go +++ b/internal/configuration/validator/configuration.go @@ -8,7 +8,7 @@ import (  )  var defaultPort = 8080 -var defaultLogsLevel = "info" +var defaultLogLevel = "info"  // Validate and adapt the configuration read from file.  func Validate(configuration *schema.Configuration, validator *schema.StructValidator) { @@ -20,8 +20,8 @@ func Validate(configuration *schema.Configuration, validator *schema.StructValid  		configuration.Port = defaultPort  	} -	if configuration.LogsLevel == "" { -		configuration.LogsLevel = defaultLogsLevel +	if configuration.LogLevel == "" { +		configuration.LogLevel = defaultLogLevel  	}  	if configuration.TLSKey != "" && configuration.TLSCert == "" { diff --git a/internal/configuration/validator/configuration_test.go b/internal/configuration/validator/configuration_test.go index 24faa68b4..83c6d6f59 100644 --- a/internal/configuration/validator/configuration_test.go +++ b/internal/configuration/validator/configuration_test.go @@ -12,7 +12,7 @@ func newDefaultConfig() schema.Configuration {  	config := schema.Configuration{}  	config.Host = "127.0.0.1"  	config.Port = 9090 -	config.LogsLevel = "info" +	config.LogLevel = "info"  	config.JWTSecret = "a_secret"  	config.AuthenticationBackend.File = new(schema.FileAuthenticationBackendConfiguration)  	config.AuthenticationBackend.File.Path = "/a/path" @@ -40,7 +40,7 @@ func TestShouldNotUpdateConfig(t *testing.T) {  	require.Len(t, validator.Errors(), 0)  	assert.Equal(t, 9090, config.Port) -	assert.Equal(t, "info", config.LogsLevel) +	assert.Equal(t, "info", config.LogLevel)  }  func TestShouldValidateAndUpdatePort(t *testing.T) { @@ -68,12 +68,12 @@ func TestShouldValidateAndUpdateHost(t *testing.T) {  func TestShouldValidateAndUpdateLogsLevel(t *testing.T) {  	validator := schema.NewStructValidator()  	config := newDefaultConfig() -	config.LogsLevel = "" +	config.LogLevel = ""  	Validate(&config, validator)  	require.Len(t, validator.Errors(), 0) -	assert.Equal(t, "info", config.LogsLevel) +	assert.Equal(t, "info", config.LogLevel)  }  func TestShouldEnsureNotifierConfigIsProvided(t *testing.T) { diff --git a/internal/logging/logger.go b/internal/logging/logger.go index e83c31781..1d9338bf8 100644 --- a/internal/logging/logger.go +++ b/internal/logging/logger.go @@ -1,16 +1,12 @@  package logging  import ( +	"os" +  	logrus_stack "github.com/Gurpartap/logrus-stack"  	"github.com/sirupsen/logrus"  ) -func init() { -	callerLevels := []logrus.Level{} -	stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel} -	logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels)) -} -  // Logger return the standard logrus logger.  func Logger() *logrus.Logger {  	return logrus.StandardLogger() @@ -20,3 +16,19 @@ func Logger() *logrus.Logger {  func SetLevel(level logrus.Level) {  	logrus.SetLevel(level)  } + +// InitializeLogger initialize logger +func InitializeLogger(filename string) error { +	callerLevels := []logrus.Level{} +	stackLevels := []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel} +	logrus.AddHook(logrus_stack.NewHook(callerLevels, stackLevels)) + +	if filename != "" { +		f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600) +		if err != nil { +			return err +		} +		logrus.SetOutput(f) +	} +	return nil +} diff --git a/internal/logging/logger_test.go b/internal/logging/logger_test.go new file mode 100644 index 000000000..6a92ca874 --- /dev/null +++ b/internal/logging/logger_test.go @@ -0,0 +1,34 @@ +package logging + +import ( +	"fmt" +	"io/ioutil" +	"log" +	"os" +	"testing" + +	"github.com/stretchr/testify/assert" +	"github.com/stretchr/testify/require" +) + +func TestShouldWriteLogsToFile(t *testing.T) { +	dir, err := ioutil.TempDir("/tmp", "logs-dir") +	if err != nil { +		log.Fatal(err) +	} +	defer os.RemoveAll(dir) + +	path := fmt.Sprintf("%s/authelia.log", dir) +	err = InitializeLogger(path) +	require.NoError(t, err) + +	Logger().Info("This is a test") + +	f, err := os.OpenFile(path, os.O_RDONLY, 0) +	require.NoError(t, err) + +	b, err := ioutil.ReadAll(f) +	require.NoError(t, err) + +	assert.Contains(t, string(b), "level=info msg=\"This is a test\"\n") +} diff --git a/internal/suites/BypassAll/configuration.yml b/internal/suites/BypassAll/configuration.yml index 1ef411b6e..de4fe375c 100644 --- a/internal/suites/BypassAll/configuration.yml +++ b/internal/suites/BypassAll/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  jwt_secret: unsecure_secret diff --git a/internal/suites/Docker/configuration.yml b/internal/suites/Docker/configuration.yml index 7e861d7de..0b1abef1d 100644 --- a/internal/suites/Docker/configuration.yml +++ b/internal/suites/Docker/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/DuoPush/configuration.yml b/internal/suites/DuoPush/configuration.yml index 343f4d52d..028d3df7d 100644 --- a/internal/suites/DuoPush/configuration.yml +++ b/internal/suites/DuoPush/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: trace +log_level: trace  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/HAProxy/configuration.yml b/internal/suites/HAProxy/configuration.yml index a69c05991..54283cd34 100644 --- a/internal/suites/HAProxy/configuration.yml +++ b/internal/suites/HAProxy/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  jwt_secret: unsecure_secret diff --git a/internal/suites/HighAvailability/configuration.yml b/internal/suites/HighAvailability/configuration.yml index b3608e2cc..facf8edd7 100644 --- a/internal/suites/HighAvailability/configuration.yml +++ b/internal/suites/HighAvailability/configuration.yml @@ -8,7 +8,7 @@ port: 9091  # Log level  #  # Level of verbosity for logs -logs_level: debug +log_level: debug  jwt_secret: unsecure_secret diff --git a/internal/suites/LDAP/configuration.yml b/internal/suites/LDAP/configuration.yml index 9d17e4076..6fb61a9eb 100644 --- a/internal/suites/LDAP/configuration.yml +++ b/internal/suites/LDAP/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/Mariadb/configuration.yml b/internal/suites/Mariadb/configuration.yml index 5daa83cbb..c67052bc1 100644 --- a/internal/suites/Mariadb/configuration.yml +++ b/internal/suites/Mariadb/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/MySQL/configuration.yml b/internal/suites/MySQL/configuration.yml index cdf215996..7d521eea8 100644 --- a/internal/suites/MySQL/configuration.yml +++ b/internal/suites/MySQL/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/NetworkACL/configuration.yml b/internal/suites/NetworkACL/configuration.yml index 8a79c1677..e10b8d297 100644 --- a/internal/suites/NetworkACL/configuration.yml +++ b/internal/suites/NetworkACL/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  jwt_secret: unsecure_password diff --git a/internal/suites/OneFactorOnly/configuration.yml b/internal/suites/OneFactorOnly/configuration.yml index eb8c17279..5ff1e87fe 100644 --- a/internal/suites/OneFactorOnly/configuration.yml +++ b/internal/suites/OneFactorOnly/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/Postgres/configuration.yml b/internal/suites/Postgres/configuration.yml index c75dabd05..a33794a2a 100644 --- a/internal/suites/Postgres/configuration.yml +++ b/internal/suites/Postgres/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080/ diff --git a/internal/suites/ShortTimeouts/configuration.yml b/internal/suites/ShortTimeouts/configuration.yml index 9988c1d3c..05cdb71cb 100644 --- a/internal/suites/ShortTimeouts/configuration.yml +++ b/internal/suites/ShortTimeouts/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  jwt_secret: unsecure_secret diff --git a/internal/suites/Standalone/configuration.yml b/internal/suites/Standalone/configuration.yml index 4fe68db98..91aa67dec 100644 --- a/internal/suites/Standalone/configuration.yml +++ b/internal/suites/Standalone/configuration.yml @@ -6,7 +6,7 @@ port: 9091  tls_cert: /var/lib/authelia/ssl/cert.pem  tls_key: /var/lib/authelia/ssl/key.pem -logs_level: debug +log_level: debug  authentication_backend:    file: diff --git a/internal/suites/Traefik/configuration.yml b/internal/suites/Traefik/configuration.yml index b0343f775..1c849b8ea 100644 --- a/internal/suites/Traefik/configuration.yml +++ b/internal/suites/Traefik/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  jwt_secret: unsecure_secret diff --git a/internal/suites/Traefik2/configuration.yml b/internal/suites/Traefik2/configuration.yml index b0343f775..1c849b8ea 100644 --- a/internal/suites/Traefik2/configuration.yml +++ b/internal/suites/Traefik2/configuration.yml @@ -4,7 +4,7 @@  port: 9091 -logs_level: debug +log_level: debug  jwt_secret: unsecure_secret diff --git a/internal/suites/example/kube/authelia/configs/configuration.yml b/internal/suites/example/kube/authelia/configs/configuration.yml index 97fae4378..3fa78e4e4 100644 --- a/internal/suites/example/kube/authelia/configs/configuration.yml +++ b/internal/suites/example/kube/authelia/configs/configuration.yml @@ -3,7 +3,7 @@  ###############################################################  port: 80 -logs_level: debug +log_level: debug  default_redirection_url: https://home.example.com:8080  | 
