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

Parse atmos.yaml CLI config when executing atmos vendor command. Improve OPA policy evaluation and error handling #222

Merged
merged 6 commits into from
Oct 20, 2022
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/auto-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
# However, using a personal access token will cause events to be triggered.
# We need that to ensure a status gets posted after the auto-format commit.
# We also want to trigger tests if the auto-format made no changes.
- uses: actions/checkout@v2
- uses: actions/checkout@v3
aknysh marked this conversation as resolved.
Show resolved Hide resolved
if: github.event.pull_request.state == 'open'
name: Privileged Checkout
with:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ jobs:
steps:
# Checkout the repo
- name: 'Checkout'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0

# Setup Go
- name: 'Setup Go'
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: '1.19'

Expand All @@ -28,7 +28,7 @@ jobs:

# Build and release
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
uses: goreleaser/goreleaser-action@v3
with:
version: latest
args: release --parallelism 2 --rm-dist
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ jobs:
timeout-minutes: 5
steps:
- name: Set up Go
uses: actions/setup-go@v2.1.3
uses: actions/setup-go@v3
with:
go-version: "1.19"
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v2.3.3
uses: actions/checkout@v3

- name: Get dependencies
run: |
Expand All @@ -48,13 +48,13 @@ jobs:
timeout-minutes: 15
steps:
- name: Set up Go
uses: actions/setup-go@v2.1.3
uses: actions/setup-go@v3
with:
go-version: "1.19"
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v2.3.3
uses: actions/checkout@v3

- name: Get dependencies
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ components:
terraform:
"infra/vpc":
vars:
name: "co!!,mmon"
cidr_block: 10.10.0.0/18
availability_zones:
- us-east-2a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# https://github.com/open-policy-agent/opa/issues/2104
# https://www.fugue.co/blog/5-tips-for-using-the-rego-language-for-open-policy-agent-opa
# https://medium.com/@agarwalshubhi17/rego-cheat-sheet-5e25faa6eee8
# https://code.tutsplus.com/tutorials/regular-expressions-with-go-part-1--cms-30403

# 'atmos' looks for the 'errors' (array of strings) output from all OPA policies
# If the 'errors' output contains one or more error messages, 'atmos' considers the policy failed
Expand All @@ -26,3 +27,15 @@ errors[message] {
count(input.vars.availability_zones) != 2
message = "In 'dev', only 2 Availability Zones are allowed"
}

# Check VPC name
errors[message] {
not re_match("^[a-zA-Z0-9]{2,20}$", input.vars.name)
message = "VPC name must be a valid string from 2 to 20 alphanumeric chars"
}

# Note:
# If a regex pattern in the `re_match` function contains a backslash to escape special chars (e.g. `\.` or `\-`),
# it must be escaped with another backslash when represented as a regular Go string (`\\.`, `\\-`).
# The reason is that backslash is also used to escape special characters in Go strings like newline (\n).
# If you want to match the backslash character itself, you'll need four slashes.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/spf13/cobra v1.6.0
github.com/spf13/viper v1.13.0
github.com/stretchr/testify v1.8.0
github.com/zclconf/go-cty v1.11.0
github.com/zclconf/go-cty v1.11.1
gopkg.in/yaml.v2 v2.4.0
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0=
github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
github.com/zclconf/go-cty v1.11.1 h1:UMMYDL4riBFaPdzjEWcDdWG7x/Adz8E8f9OX/MGR7V4=
github.com/zclconf/go-cty v1.11.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
Expand Down
20 changes: 15 additions & 5 deletions internal/exec/validate_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"github.com/pkg/errors"
"strings"
"time"

u "github.com/cloudposse/atmos/pkg/utils"
"github.com/open-policy-agent/opa/sdk"
Expand Down Expand Up @@ -74,10 +75,12 @@ func ValidateWithOpa(data any, schemaName string, schemaText string) (bool, erro
return false, err
}

ctx := context.Background()
// Set timeout for schema validation
ctx, cancelFunc := context.WithTimeout(context.TODO(), time.Second*7)
defer cancelFunc()

// '/bundles/' prefix is required by the OPA SDK
bundleSchemaName := "/bundles/" + schemaName
bundleSchemaName := "/bundles/validate"

// Create a bundle server
server, err := opaTestServer.NewServer(opaTestServer.MockBundle(bundleSchemaName, map[string]string{schemaName: schemaText}))
Expand All @@ -98,17 +101,21 @@ func ValidateWithOpa(data any, schemaName string, schemaText string) (bool, erro
"validate": {
"resource": %s
}
},
"decision_logs": {
"console": false
}
}`, server.URL(), bundleSchemaName))

timeoutErrorMessage := "Timeout evaluating the OPA policy. Please check the following:\n" +
"1. Rego syntax\n" +
"2. If 're_match' function is used and the regex pattern contains a backslash to escape special chars, the backslash itself must be escaped with another backslash"

// Create an instance of the OPA object
opa, err := sdk.New(ctx, sdk.Options{
Config: bytes.NewReader(config),
})
if err != nil {
if err.Error() == "context deadline exceeded" {
err = errors.New(timeoutErrorMessage)
}
return false, err
}

Expand All @@ -119,6 +126,9 @@ func ValidateWithOpa(data any, schemaName string, schemaText string) (bool, erro
Path: "/atmos/errors",
Input: dataFromJson,
}); err != nil {
if err.Error() == "context deadline exceeded" {
err = errors.New(timeoutErrorMessage)
}
return false, err
}

Expand Down
2 changes: 1 addition & 1 deletion internal/exec/vendor_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
func ExecuteVendorCommand(cmd *cobra.Command, args []string, vendorCommand string) error {
// InitCliConfig finds and merges CLI configurations in the following order:
// system dir, home dir, current dir, ENV vars, command-line arguments
cliConfig, err := cfg.InitCliConfig(cfg.ConfigAndStacksInfo{}, false)
cliConfig, err := cfg.InitCliConfig(cfg.ConfigAndStacksInfo{}, true)
if err != nil {
return err
}
Expand Down