Skip to content

Commit

Permalink
add ini support
Browse files Browse the repository at this point in the history
  • Loading branch information
boranx committed Jul 25, 2019
1 parent 32db102 commit 2dba479
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -70,7 +70,7 @@ You can find examples using various other tools in the `examples ` directory, in
* [Kustomize](examples/kustomize)
* [Terraform](examples/terraform)
* [Serverless Framework](examples/serverless)

* [INI](examples/ini)

## Configuration and external policies

Expand Down
6 changes: 6 additions & 0 deletions acceptance.bats
Expand Up @@ -70,6 +70,12 @@
[[ "$output" =~ "The image port should be 8080 in deployment.cue. you got : 8081" ]]
}

@test "Can parse ini files" {
run ./conftest test -p examples/ini/policy examples/ini/grafana.ini
[ "$status" -eq 1 ]
[[ "$output" =~ "Users should verify their e-mail address" ]]
}

@test "Can disable color" {
run ./conftest test -p examples/kubernetes/policy examples/kubernetes/service.yaml --no-color
[ "$status" -eq 0 ]
Expand Down
117 changes: 117 additions & 0 deletions examples/ini/grafana.ini
@@ -0,0 +1,117 @@
# possible values : production, development
app_mode = production

# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty
instance_name = ${HOSTNAME}

#################################### Server ##############################
[server]
# Protocol (http, https, socket)
protocol = http

# The ip address to bind to, empty will bind to all interfaces
http_addr =

# The http port to use
http_port = 3000

# The public facing domain name used to access grafana from a browser
domain = localhost

# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
enforce_domain = false

# The full public facing url
root_url = %(protocol)s://%(domain)s:%(http_port)s/

# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
serve_from_sub_path = false

# Log web requests
router_logging = false

# the path relative working path
static_root_path = public

# enable gzip
enable_gzip = false

#################################### Users ###############################
[users]
# disable user signup / registration
allow_sign_up = false

# Allow non admin users to create organizations
allow_org_create = false

# Set to true to automatically assign new users to the default organization (id 1)
auto_assign_org = true

# Set this value to automatically add new users to the provided organization (if auto_assign_org above is set to true)
auto_assign_org_id = 1

# Default role new users will be automatically assigned (if auto_assign_org above is set to true)
auto_assign_org_role = Viewer

# Require email validation before sign up completes
verify_email_enabled = false

# Background text for the user field on the login page
login_hint = email or username
password_hint = password

# Default UI theme ("dark" or "light")
default_theme = dark

# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
viewers_can_edit = false

# Editors can administrate dashboard, folders and teams they create
editors_can_admin = false

#################################### Alerting ############################
[alerting]
# Disable alerting engine & UI features
enabled = true
# Makes it possible to turn off alert rule execution but alerting UI is visible
execute_alerts = true

# Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state)
error_or_timeout = alerting

# Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok)
nodata_or_nullvalues = no_data

# Alert notifications can include images, but rendering many images at the same time can overload the server
# This limit will protect the server from render overloading and make sure notifications are sent out quickly
concurrent_render_limit = 5

# Default setting for alert calculation timeout. Default value is 30
evaluation_timeout_seconds = 30

# Default setting for alert notification timeout. Default value is 30
notification_timeout_seconds = 30

# Default setting for max attempts to sending alert notifications. Default value is 3
max_attempts = 3

[auth]
# Login cookie name
login_cookie_name = grafana_session

# The lifetime (days) an authenticated user can be inactive before being required to login at next visit. Default is 7 days.
login_maximum_inactive_lifetime_days = 7

# The maximum lifetime (days) an authenticated user can be logged in since login time before being required to login. Default is 30 days.
login_maximum_lifetime_days = 30

# How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
token_rotation_interval_minutes = 10

# Set to true to disable (hide) the login form, useful if you use OAuth
disable_login_form = false

#################################### Basic Auth ##########################
[auth.basic]
enabled = true
31 changes: 31 additions & 0 deletions examples/ini/policy/deny.rego
@@ -0,0 +1,31 @@
package main

deny[msg] {
not input.alerting.enabled = "true"
msg = "Alerting should turned on"
}

deny[msg] {
not input["auth.basic"].enabled = "true"
msg = "Basic auth should be enabled"
}

deny[msg] {
not input.server.http_port = "3000"
msg = "Grafana port should be 3000"
}

deny[msg] {
not input.server.protocol = "http"
msg = "Grafana should use default http"
}

deny[msg] {
not input.users.allow_sign_up = "false"
msg = "Users cannot sign up themselves"
}

deny[msg] {
not input.users.verify_email_enabled = "true"
msg = "Users should verify their e-mail address"
}
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -16,6 +16,7 @@ require (
github.com/docker/docker-credential-helpers v0.6.2 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/ghodss/yaml v1.0.0
github.com/go-ini/ini v1.44.0
github.com/gobwas/glob v0.2.3 // indirect
github.com/gorilla/mux v1.7.1 // indirect
github.com/hashicorp/go-multierror v1.0.0
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Expand Up @@ -148,6 +148,8 @@ github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-ini/ini v1.44.0 h1:8+SRbfpRFlIunpSum4BEf1ClTtVjOgKzgBv9pHFkI6w=
github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
Expand Down Expand Up @@ -267,6 +269,7 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
github.com/joyent/triton-go v0.0.0-20180313100802-d8f9c0314926/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
Expand Down Expand Up @@ -438,7 +441,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo=
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
Expand Down Expand Up @@ -646,6 +651,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v1 v1.1.2/go.mod h1:QpYS+a4WhS+DTlyQIi6Ka7MS3SuR9a055rgXNEe6EiA=
Expand Down
42 changes: 42 additions & 0 deletions pkg/parser/ini/ini.go
@@ -0,0 +1,42 @@
package ini

import (
"encoding/json"
"fmt"
"path/filepath"

"github.com/ghodss/yaml"
"github.com/go-ini/ini"
)

type Parser struct {
FileName string
}

func (i *Parser) Unmarshal(p []byte, v interface{}) error {
filePath, _ := filepath.Abs(i.FileName)
result := map[string]map[string]string{}
cfg, err := ini.Load(filePath)
if err != nil {
return fmt.Errorf("Fail to read ini file: %v", err)
}

sections := cfg.Sections()
for _, s := range sections {
sectionName := s.Name()
if sectionName == "DEFAULT" {
continue
}
result[sectionName] = map[string]string{}
result[sectionName] = s.KeysHash()
}
j, err := json.Marshal(result)
if err != nil {
return fmt.Errorf("Error trying to parse ini to json: %s", err)
}
err = yaml.Unmarshal(j, v)
if err != nil {
return fmt.Errorf("Unable to parse YAML from ini-json %s: %s", i.FileName, err)
}
return nil
}
27 changes: 27 additions & 0 deletions pkg/parser/ini/ini_test.go
@@ -0,0 +1,27 @@
package ini

import (
"testing"
)

func TestIniParser(t *testing.T) {
parser := &Parser{
FileName: "sample.ini",
}

var input interface{}
err := parser.Unmarshal(nil, &input)
if err != nil {
t.Fatalf("parser should not have thrown an error: %v", err)
}

if input == nil {
t.Error("There should be information parsed but its nil")
}

inputMap := input.(map[string]interface{})
item := inputMap["Local Varaibles"]
if len(item.(map[string]interface{})) <= 0 {
t.Error("There should be at least one item defined in the parsed file, but none found")
}
}
10 changes: 10 additions & 0 deletions pkg/parser/ini/sample.ini
@@ -0,0 +1,10 @@
[Local Varaibles]
Name=name
Title=title
Visisbility=show/hide

[Navigation Controls]
OnNext=node path
Help=help file

# Test comment
5 changes: 5 additions & 0 deletions pkg/parser/parser.go
Expand Up @@ -4,6 +4,7 @@ import (
"path/filepath"

"github.com/instrumenta/conftest/pkg/parser/cue"
"github.com/instrumenta/conftest/pkg/parser/ini"
"github.com/instrumenta/conftest/pkg/parser/terraform"
"github.com/instrumenta/conftest/pkg/parser/toml"
"github.com/instrumenta/conftest/pkg/parser/yaml"
Expand Down Expand Up @@ -32,6 +33,10 @@ func GetParser(fileName string) Parser {
return &cue.Parser{
FileName: fileName,
}
case ".ini":
return &ini.Parser{
FileName: fileName,
}
default:
return &yaml.Parser{
FileName: fileName,
Expand Down

0 comments on commit 2dba479

Please sign in to comment.