Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

312 #315

Merged
merged 5 commits into from
Apr 1, 2023
Merged

312 #315

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions ReadMe.Md
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,6 @@ Loglevel for stdout, one of TRACE, DEBUG, INFO or WARN
LOGLEVEL="DEBUG"
```

#### TZ

TimeZone

```bash
TZ="Australia/Sydney"
```

## Contributions

The j8a team welcomes all [contributors](https://github.com/simonmittag/j8a/blob/master/CONTRIBUTING.md). Everyone
Expand Down
51 changes: 50 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ import (
"github.com/rs/zerolog/log"
)

//Config is the system wide configuration for j8a
// Config is the system wide configuration for j8a
type Config struct {
Policies map[string]Policy
Routes Routes
Jwt map[string]*Jwt
Resources map[string][]ResourceMapping
Connection Connection
DisableXRequestInfo bool
TimeZone string
LogLevel string
}

const HTTP = "HTTP"
Expand Down Expand Up @@ -110,6 +112,53 @@ func (config Config) parse(yml []byte) *Config {
return &config
}

func (config Config) validateLogLevel() *Config {
logLevel := strings.ToUpper(config.LogLevel)
old := strings.ToUpper(zerolog.GlobalLevel().String())

if len(logLevel) > 0 && logLevel != old {
switch logLevel {
case "TRACE":
log.Info().Msgf("resetting global log level to %v", logLevel)
zerolog.SetGlobalLevel(zerolog.TraceLevel)
case "DEBUG":
log.Info().Msgf("resetting global log level to %v", logLevel)
zerolog.SetGlobalLevel(zerolog.DebugLevel)
case "INFO":
log.Info().Msgf("resetting global log level to %v", logLevel)
zerolog.SetGlobalLevel(zerolog.InfoLevel)
case "WARN":
log.Info().Msgf("resetting global log level to %v", logLevel)
zerolog.SetGlobalLevel(zerolog.WarnLevel)
default:
config.panic(fmt.Sprintf("invalid log level %v must be one of TRACE | DEBUG | INFO | WARN ", logLevel))
}
}

return &config
}

func (config Config) validateTimeZone() *Config {
var tz *time.Location
var e error
if len(config.TimeZone) > 0 {
tz, e = time.LoadLocation(config.TimeZone)
if e != nil {
config.panic(fmt.Sprintf("Not a valid TimeZone identifier %s, see: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones", config.TimeZone))
}
} else {
//we default to UTC if time wasn't specified
tz = time.UTC
}

zerolog.TimestampFunc = func() time.Time {
return time.Now().In(tz)
}
log.Info().Msgf("timeZone for this log and all system events set to %s", tz.String())

return &config
}

func (config Config) reApplyResourceNames() *Config {
for name := range config.Resources {
resourceMappings := config.Resources[name]
Expand Down
87 changes: 55 additions & 32 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,35 @@ func TestMain(m *testing.M) {
}

func testSetup() {
os.Setenv("TZ", "Australia/Sydney")
os.Setenv("LOGLEVEL", "TRACE")
os.Setenv("LOGCOLOR", "true")
}

//TestDefaultDownstreamReadTimeout
func TestTimeZones(t *testing.T) {
tzs := []struct {
tz string
valid bool
}{
{
"Australia/Sydney", true,
},
{
"Africa/Johannesburg", true,
},
{
"UTC", true,
},
}

config := new(Config)
for _, tz := range tzs {
config.TimeZone = tz.tz
config.validateTimeZone()
}

}

// TestDefaultDownstreamReadTimeout
func TestDefaultDownstreamReadTimeout(t *testing.T) {
config := new(Config).setDefaultDownstreamParams()
got := config.Connection.Downstream.ReadTimeoutSeconds
Expand All @@ -31,7 +54,7 @@ func TestDefaultDownstreamReadTimeout(t *testing.T) {
}
}

//TestDefaultDownstreamIdleTimeout
// TestDefaultDownstreamIdleTimeout
func TestDefaultDownstreamIdleTimeout(t *testing.T) {
config := new(Config).setDefaultDownstreamParams()
got := config.Connection.Downstream.IdleTimeoutSeconds
Expand All @@ -41,7 +64,7 @@ func TestDefaultDownstreamIdleTimeout(t *testing.T) {
}
}

//TestDefaultDownstreamRoundtripTimeout
// TestDefaultDownstreamRoundtripTimeout
func TestDefaultDownstreamRoundtripTimeout(t *testing.T) {
config := new(Config).setDefaultDownstreamParams()
got := config.Connection.Downstream.RoundTripTimeoutSeconds
Expand All @@ -60,7 +83,7 @@ func TestDefaultDownstreamMaxBodyBytes(t *testing.T) {
}
}

//TestDefaultUpstreamSocketTimeout
// TestDefaultUpstreamSocketTimeout
func TestDefaultUpstreamSocketTimeout(t *testing.T) {
config := new(Config).setDefaultUpstreamParams()
got := config.Connection.Upstream.SocketTimeoutSeconds
Expand All @@ -70,7 +93,7 @@ func TestDefaultUpstreamSocketTimeout(t *testing.T) {
}
}

//TestDefaultUpstreamSocketTimeout
// TestDefaultUpstreamSocketTimeout
func TestDefaultUpstreamReadTimeout(t *testing.T) {
config := new(Config).setDefaultUpstreamParams()
got := config.Connection.Upstream.ReadTimeoutSeconds
Expand All @@ -80,7 +103,7 @@ func TestDefaultUpstreamReadTimeout(t *testing.T) {
}
}

//TestDefaultUpstreamIdleTimeout
// TestDefaultUpstreamIdleTimeout
func TestDefaultUpstreamIdleTimeout(t *testing.T) {
config := new(Config).setDefaultUpstreamParams()
got := config.Connection.Upstream.IdleTimeoutSeconds
Expand All @@ -90,7 +113,7 @@ func TestDefaultUpstreamIdleTimeout(t *testing.T) {
}
}

//TestDefaultUpstreamConnectionPoolSize
// TestDefaultUpstreamConnectionPoolSize
func TestDefaultUpstreamConnectionPoolSize(t *testing.T) {
config := new(Config).setDefaultUpstreamParams()
got := config.Connection.Upstream.PoolSize
Expand All @@ -100,7 +123,7 @@ func TestDefaultUpstreamConnectionPoolSize(t *testing.T) {
}
}

//TestDefaultUpstreamConnectionMaxAttempts
// TestDefaultUpstreamConnectionMaxAttempts
func TestDefaultUpstreamConnectionMaxAttempts(t *testing.T) {
config := new(Config).setDefaultUpstreamParams()
got := config.Connection.Upstream.MaxAttempts
Expand All @@ -110,7 +133,7 @@ func TestDefaultUpstreamConnectionMaxAttempts(t *testing.T) {
}
}

//TestDefaultPolicy
// TestDefaultPolicy
func TestDefaultPolicy(t *testing.T) {
wantLabel := "default"

Expand Down Expand Up @@ -159,7 +182,7 @@ func TestParsePolicy(t *testing.T) {
}
}

//TestParseResource
// TestParseResource
func TestParseResource(t *testing.T) {
configJson := []byte("{\n\t\"resources\": {\n\t\t\"customer\": [{\n\t\t\t\"labels\": [\n\t\t\t\t\"blue\"\n\t\t\t],\n\t\t\t\"url\": {\n\t\t\t\t\"scheme\": \"http\",\n\t\t\t\t\"host\": \"localhost\",\n\t\t\t\t\"port\": 8081\n\t\t\t}\n\t\t}]\n\t}\n}")
config := new(Config).parse(configJson)
Expand All @@ -181,7 +204,7 @@ func TestParseResource(t *testing.T) {
}
}

//TestParseConnection
// TestParseConnection
func TestParseConnection(t *testing.T) {
configJson := []byte("{\n\t\"connection\": {\n\t\t\"downstream\": {\n\t\t\t\"readTimeoutSeconds\": 120,\n\t\t\t\"roundTripTimeoutSeconds\": 240,\n\t\t\t\"idleTimeoutSeconds\": 30,\n\t\t\t\"port\": 8080,\n\t\t\t\"mode\": \"TLS\"\n\t\t},\n\t\t\"upstream\": {\n\t\t\t\"socketTimeoutSeconds\": 3,\n\t\t\t\"readTimeoutSeconds\": 120,\n\t\t\t\"idleTimeoutSeconds\": 120,\n\t\t\t\"maxAttempts\": 4,\n\t\t\t\"poolSize\": 1024\n\t\t}\n\t}\n}")
config := new(Config).parse(configJson)
Expand Down Expand Up @@ -245,7 +268,7 @@ func TestParseConnection(t *testing.T) {
}
}

//TestParseRoute
// TestParseRoute
func TestParseRoute(t *testing.T) {
configJson := []byte("{\"routes\": [{\n\t\t\t\"path\": \"/about\",\n\t\t\t\"resource\": \"aboutj8a\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"/customer\",\n\t\t\t\"resource\": \"customer\",\n\t\t\t\"policy\": \"ab\"\n\t\t}\n\t]}")
config := new(Config).parse(configJson)
Expand All @@ -264,7 +287,7 @@ func TestParseRoute(t *testing.T) {
}
}

//TestValidateAcmeEmail
// TestValidateAcmeEmail
func TestValidateAcmeEmail(t *testing.T) {
config := &Config{
Connection: Connection{
Expand All @@ -284,7 +307,7 @@ func TestValidateAcmeEmail(t *testing.T) {
config = config.validateAcmeConfig()
}

//TestValidateAcmeEmail
// TestValidateAcmeEmail
func TestValidateAcmeGracePeriod30(t *testing.T) {
config := &Config{
Connection: Connection{
Expand Down Expand Up @@ -390,7 +413,7 @@ func TestValidateAcmeGracePeriodFailsGreater30(t *testing.T) {
config = config.validateAcmeConfig()
}

//TestValidateAcmeDomainInvalidLeadingDotFails
// TestValidateAcmeDomainInvalidLeadingDotFails
func TestValidateValidateAcmeDomainInvalidLeadingDotFails(t *testing.T) {
defer func() {
if r := recover(); r == nil {
Expand All @@ -402,7 +425,7 @@ func TestValidateValidateAcmeDomainInvalidLeadingDotFails(t *testing.T) {
t.Errorf("config did not panic for supported Acme provider but with missing domain")
}

//TestValidateAcmeDomainInvalidTrailingDotFails
// TestValidateAcmeDomainInvalidTrailingDotFails
func TestValidateAcmeDomainInvalidTrailingDotFails(t *testing.T) {
defer func() {
if r := recover(); r == nil {
Expand All @@ -414,8 +437,8 @@ func TestValidateAcmeDomainInvalidTrailingDotFails(t *testing.T) {
t.Errorf("config did not panic for supported Acme provider but with missing domain")
}

//TestValidateAcmeDomainInvalidTrailingDotFails
//NOTE WE DO NOT SUPPORT WILDCART CERTS BECAUSE THEY CANNOT BE VERIFIED USING HTTP01 CHALLENGE ON LETSENCRYPT, SEE: https://letsencrypt.org/docs/faq/
// TestValidateAcmeDomainInvalidTrailingDotFails
// NOTE WE DO NOT SUPPORT WILDCART CERTS BECAUSE THEY CANNOT BE VERIFIED USING HTTP01 CHALLENGE ON LETSENCRYPT, SEE: https://letsencrypt.org/docs/faq/
func TestValidateAcmeDomainInvalidWildcartCertFails(t *testing.T) {
defer func() {
if r := recover(); r == nil {
Expand All @@ -427,7 +450,7 @@ func TestValidateAcmeDomainInvalidWildcartCertFails(t *testing.T) {
t.Errorf("config did not panic for supported Acme provider but with missing domain")
}

//TestValidateAcmeDomainValidSubdomainPasses
// TestValidateAcmeDomainValidSubdomainPasses
func TestValidateAcmeDomainValidSubdomainPasses(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand All @@ -439,7 +462,7 @@ func TestValidateAcmeDomainValidSubdomainPasses(t *testing.T) {
t.Logf("normal. config did not panic for valid subdomain and supported Acme provider")
}

//TestValidateAcmeDomainMissingFails
// TestValidateAcmeDomainMissingFails
func TestValidateAcmeDomainMissingFails(t *testing.T) {
defer func() {
if r := recover(); r == nil {
Expand All @@ -465,7 +488,7 @@ func TestValidateAcmeDomainMissingFails(t *testing.T) {
t.Errorf("config did not panic for supported Acme provider but with missing domain")
}

//TestValidateAcmeProviderLetsencrypt
// TestValidateAcmeProviderLetsencrypt
func TestValidateAcmeProviderLetsencrypt(t *testing.T) {
config := &Config{
Connection: Connection{
Expand All @@ -486,7 +509,7 @@ func TestValidateAcmeProviderLetsencrypt(t *testing.T) {
t.Logf("normal. no config panic for Acme provider letsencrypt")
}

//TestValidateAcmeProviderLetsencryptWithMultipleSubDomains
// TestValidateAcmeProviderLetsencryptWithMultipleSubDomains
func TestValidateAcmeProviderLetsencryptWithMultipleSubdomains(t *testing.T) {
config := &Config{
Connection: Connection{
Expand All @@ -507,7 +530,7 @@ func TestValidateAcmeProviderLetsencryptWithMultipleSubdomains(t *testing.T) {
t.Logf("normal. no config panic for Acme provider letsencrypt")
}

//TestValidateAcmeProviderLetsencryptFailsWithOneInvalidSubDomain
// TestValidateAcmeProviderLetsencryptFailsWithOneInvalidSubDomain
func TestValidateAcmeProviderLetsencryptFailsWithOneInvalidSubDomain(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand All @@ -533,7 +556,7 @@ func TestValidateAcmeProviderLetsencryptFailsWithOneInvalidSubDomain(t *testing.
t.Errorf("config did not panic for invalid subdomain")
}

//TestValidateAcmeProviderLetsencrypt
// TestValidateAcmeProviderLetsencrypt
func TestValidateAcmeProviderPort80(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand Down Expand Up @@ -562,7 +585,7 @@ func TestValidateAcmeProviderPort80(t *testing.T) {
t.Logf("normal. no config panic for Acme provider letsencrypt with port 80")
}

//TestValidateAcmeProviderFailsWithMissingPort80
// TestValidateAcmeProviderFailsWithMissingPort80
func TestValidateAcmeProviderFailsWithMissingPort80(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand All @@ -588,7 +611,7 @@ func TestValidateAcmeProviderFailsWithMissingPort80(t *testing.T) {
t.Error("no config panic for Acme provider without port 80 specified. should have panicked")
}

//TestValidateAcmeProviderFailsWithCertSpecified
// TestValidateAcmeProviderFailsWithCertSpecified
func TestValidateAcmeProviderFailsWithCertSpecified(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand Down Expand Up @@ -616,7 +639,7 @@ func TestValidateAcmeProviderFailsWithCertSpecified(t *testing.T) {
t.Error("no config panic happened after superfluous cert specified but it should have")
}

//TestValidateAcmeProviderFailsWithKeySpecified
// TestValidateAcmeProviderFailsWithKeySpecified
func TestValidateAcmeProviderFailsWithKeySpecified(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand Down Expand Up @@ -644,7 +667,7 @@ func TestValidateAcmeProviderFailsWithKeySpecified(t *testing.T) {
t.Error("no config panic occurred after extra private key specified next to acme")
}

//TestValidateAcmeMissingProviderFails
// TestValidateAcmeMissingProviderFails
func TestValidateAcmeMissingProviderFails(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand All @@ -670,7 +693,7 @@ func TestValidateAcmeMissingProviderFails(t *testing.T) {
t.Errorf("config did not panic for missing provider")
}

//TestValidateAcmeMissingEmailFails
// TestValidateAcmeMissingEmailFails
func TestValidateAcmeEmailFails(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand All @@ -696,7 +719,7 @@ func TestValidateAcmeEmailFails(t *testing.T) {
t.Errorf("config did not panic for missing email")
}

//TestValidateAcmeInvalidEmailFails
// TestValidateAcmeInvalidEmailFails
func TestValidateAcmeInvalidEmailFails(t *testing.T) {
defer func() {
if r := recover(); r != nil {
Expand Down Expand Up @@ -771,7 +794,7 @@ func TestTlsInsecureSkipVerify_Optional(t *testing.T) {
}
}

//TestReadConfigFile
// TestReadConfigFile
func TestReadConfigFile(t *testing.T) {
config := new(Config).readYmlFile("./j8acfg.yml")
if config.Routes == nil {
Expand Down
2 changes: 2 additions & 0 deletions integration/j8a1.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
---
timeZone: Australia/Sydney
logLevel: info
connection:
downstream:
readTimeoutSeconds: 3
Expand Down
Loading