Skip to content

Commit

Permalink
Merge pull request #267 from accurics/terrascan-v1.0-policy-support
Browse files Browse the repository at this point in the history
Terrascan v1.0 policy support
  • Loading branch information
Willie authored Aug 10, 2020
2 parents 7b940a9 + dbdbe25 commit 9331bf2
Show file tree
Hide file tree
Showing 112 changed files with 2,180 additions and 30 deletions.
3 changes: 2 additions & 1 deletion cmd/terrascan/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func main() {
iacVersion = flag.String("iac-version", "default", "IaC version (supported values: 'v12' for terraform)")
iacFilePath = flag.String("f", "", "IaC file path")
iacDirPath = flag.String("d", "", "IaC directory path")
policyPath = flag.String("p", "", "Policy directory path")

// cloud flags
cloudType = flag.String("cloud", "", "cloud provider (supported values: aws)")
Expand All @@ -64,6 +65,6 @@ func main() {
} else {
logging.Init(*logType, *logLevel)
zap.S().Debug("running terrascan in cli mode")
cli.Run(*iacType, *iacVersion, *cloudType, *iacFilePath, *iacDirPath, *configFile)
cli.Run(*iacType, *iacVersion, *cloudType, *iacFilePath, *iacDirPath, *configFile, *policyPath)
}
}
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ require (
github.com/hashicorp/go-version v1.2.0
github.com/hashicorp/hcl/v2 v2.3.0
github.com/hashicorp/terraform v0.12.28
github.com/open-policy-agent/opa v0.22.0
github.com/pelletier/go-toml v1.8.0
github.com/pkg/errors v0.9.1
github.com/spf13/afero v1.3.2
github.com/zclconf/go-cty v1.2.1
go.uber.org/zap v1.9.1
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/tools v0.0.0-20200728160517-2ad651e9e297 // indirect
honnef.co/go/tools v0.0.1-2020.1.4 // indirect
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/tools v0.0.0-20200809012840-6f4f008689da // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
honnef.co/go/tools v0.0.1-2020.1.5 // indirect
)
75 changes: 59 additions & 16 deletions go.sum

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions pkg/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,23 @@
package cli

import (
// "os"

"github.com/accurics/terrascan/pkg/runtime"
// "github.com/accurics/terrascan/pkg/utils"
)

// Run executes terrascan in CLI mode
func Run(iacType, iacVersion, cloudType, iacFilePath, iacDirPath, configFile string) {
func Run(iacType, iacVersion, cloudType, iacFilePath, iacDirPath, configFile, policyPath string) {

// create a new runtime executor for processing IaC
executor, err := runtime.NewExecutor(iacType, iacVersion, cloudType, iacFilePath,
iacDirPath, configFile)
iacDirPath, configFile, policyPath)
if err != nil {
return
}

// executor output
_, err = executor.Execute()
if err != nil {
return
}
// utils.PrintJSON(normalized, os.Stdout)
// utils.PrintJSON(violations, os.Stdout)
}
24 changes: 24 additions & 0 deletions pkg/data/file/importer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package file

// Info File info
type Info struct {
Path string
Hash string
HashType string
Attributes string
}

// Group Group metadata
type Group struct {
Name string
IsReadOnly bool
VerifySignatures bool
Directories []*Info
Files []*Info
}

// Metadata File metadata
type Metadata struct {
Version string
Groups []*Group
}
2 changes: 1 addition & 1 deletion pkg/http-server/file-scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) {

// create a new runtime executor for scanning the uploaded file
executor, err := runtime.NewExecutor(iacType, iacVersion, cloudType,
tempFile.Name(), "", "")
tempFile.Name(), "", "", "")
if err != nil {
zap.S().Error(err)
apiErrorResponse(w, err.Error(), http.StatusBadRequest)
Expand Down
2 changes: 1 addition & 1 deletion pkg/notifications/notifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func NewNotifiers(configFile string) ([]Notifier, error) {

// empty config file path
if configFile == "" {
zap.S().Infof("no config file specified")
zap.S().Debug("no config file specified")
return notifiers, nil
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "cloudfrontNoHTTPSTraffic",
"file": "cloudfrontNoHTTPSTraffic.rego",
"ruleTemplate": "cloudfrontNoHTTPSTraffic",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "HIGH",
"description": "Use encrypted connection between CloudFront and origin server",
"ruleReferenceId": "AWS.CloudFront.EncryptionandKeyManagement.High.0407",
"category": "Encryption and Key Management",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "cloudfrontNoSecureCiphers",
"file": "cloudfrontNoSecureCiphers.rego",
"ruleTemplate": "cloudfrontNoSecureCiphers",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "HIGH",
"description": "Secure ciphers are not used in CloudFront distribution",
"ruleReferenceId": "AWS.CloudFront.EncryptionandKeyManagement.High.0408",
"category": "Encryption and Key Management",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "cloudfrontNoLogging",
"file": "cloudfrontNoLogging.rego",
"ruleTemplate": "cloudfrontNoLogging",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "MEDIUM",
"description": "Ensure that your AWS Cloudfront distributions have the Logging feature enabled in order to track all viewer requests for the content delivered through the Content Delivery Network (CDN).",
"ruleReferenceId": "AWS.CloudFront.Logging.Medium.0567",
"category": "Logging",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package accurics

{{.prefix}}cloudfrontNoHTTPSTraffic[retVal]{
cloudfront = input.aws_cloudfront_distribution[_]
some i
orderedcachebehaviour = cloudfront.config.ordered_cache_behavior[i]
orderedcachebehaviour.viewer_protocol_policy == "allow-all"
traverse := sprintf("ordered_cache_behavior[%d].viewer_protocol_policy", [i])
retVal := { "Id": cloudfront.id, "ReplaceType": "edit", "CodeType": "attribute", "Traverse": traverse, "Attribute": "ordered_cache_behavior.viewer_protocol_policy", "AttributeDataType": "string", "Expected": "redirect-to-https", "Actual": orderedcachebehaviour.viewer_protocol_policy }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package accurics

{{.prefix}}cloudfrontNoLogging[retVal]{
cloudfront = input.aws_cloudfront_distribution[_]
not cloudfront.config.logging_config

rc = "ewogICJsb2dnaW5nX2NvbmZpZyI6IHsKICAgICJpbmNsdWRlX2Nvb2tpZXMiOiBmYWxzZSwKICAgICJidWNrZXQiOiAiPGJ1Y2tldD4iLAogICAgInByZWZpeCI6ICI8cHJlZml4PiIKICB9Cn0="

traverse = ""
retVal := { "Id": cloudfront.id, "ReplaceType": "add", "CodeType": "block", "Traverse": traverse, "Attribute": "logging_config", "AttributeDataType": "base64", "Expected": rc, "Actual": null }
}

{{.prefix}}cloudfrontNoLogging[retVal]{
cloudfront = input.aws_cloudfront_distribution[_]
cloudfront.config.logging_config == []

rc = "ewogICJsb2dnaW5nX2NvbmZpZyI6IHsKICAgICJpbmNsdWRlX2Nvb2tpZXMiOiBmYWxzZSwKICAgICJidWNrZXQiOiAiPGJ1Y2tldD4iLAogICAgInByZWZpeCI6ICI8cHJlZml4PiIKICB9Cn0="

traverse = ""
retVal := { "Id": cloudfront.id, "ReplaceType": "add", "CodeType": "block", "Traverse": traverse, "Attribute": "logging_config", "AttributeDataType": "base64", "Expected": rc, "Actual": null }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package accurics

{{.prefix}}cloudfrontNoSecureCiphers[retVal]{
cloudfront = input.aws_cloudfront_distribution[_]
some i
certificate = cloudfront.config.viewer_certificate[i]
certificate.cloudfront_default_certificate = false
not minimumAllowedProtocolVersion(certificate.minimum_protocol_version)
traverse := sprintf("viewer_certificate[%d].minimum_protocol_version", [i])
retVal := { "Id": cloudfront.id, "ReplaceType": "edit", "CodeType": "attribute", "Traverse": traverse, "Attribute": "viewer_certificate.minimum_protocol_version", "AttributeDataType": "string", "Expected": "TLSv1.2", "Actual": certificate.minimum_protocol_version }
}

minimumAllowedProtocolVersion(currentVersion) {
currentVersion == "TLSv1.1"
}

minimumAllowedProtocolVersion(currentVersion) {
currentVersion == "TLSv1.2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "cloudTrailLogNotEncrypted",
"file": "cloudTrailLogNotEncrypted.rego",
"ruleTemplate": "cloudTrailLogNotEncrypted",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "HIGH",
"description": "Cloud Trail Log Not Enabled",
"ruleReferenceId": "AWS.CloudTrail.Logging.High.0399",
"category": "Logging",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "reme_enableSNSTopic",
"file": "enableSNSTopic.rego",
"ruleTemplate": "enableSNSTopic",
"ruleTemplateArgs": {
"prefix": "reme_"
},
"severity": "MEDIUM",
"description": "Ensure appropriate subscribers to each SNS topic",
"ruleReferenceId": "AWS.CloudTrail.Logging.Low.0559",
"category": "Logging",
"version": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "cloudTrailMultiRegionNotCreated",
"file": "cloudTrailMultiRegionNotCreated.rego",
"ruleTemplate": "cloudTrailMultiRegionNotCreated",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "MEDIUM",
"description": "Cloud Trail Multi Region not enabled",
"ruleReferenceId": "AWS.CloudTrail.Logging.Medium.0460",
"category": "Logging",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package accurics

{{.prefix}}cloudTrailLogNotEncrypted[retVal]{
cloud_trail = input.aws_cloudtrail[_]
cloud_trail.config.kms_key_id == null

traverse = "kms_key_id"
retVal := { "Id": cloud_trail.id, "ReplaceType": "edit", "CodeType": "attribute", "Traverse": traverse, "Attribute": "kms_key_id", "AttributeDataType": "string", "Expected": "<kms_key_id>", "Actual": cloud_trail.config.kms_key_id }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package accurics

{{.prefix}}cloudTrailMultiRegionNotCreated[retVal]{
cloud_trail = input.aws_cloudtrail[_]
cloud_trail.config.is_multi_region_trail == false

traverse = "is_multi_region_trail"
retVal := { "Id": cloud_trail.id, "ReplaceType": "edit", "CodeType": "attribute", "Traverse": traverse, "Attribute": "is_multi_region_trail", "AttributeDataType": "bool", "Expected": true, "Actual": cloud_trail.config.is_multi_region_trail }
}
6 changes: 6 additions & 0 deletions pkg/policies/opa/rego/aws/aws_cloudtrail/enableSNSTopic.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package accurics

{{.prefix}}enableSNSTopic[sns.id] {
sns := input.aws_cloudtrail[_]
sns.config.sns_topic_name == null
}
13 changes: 13 additions & 0 deletions pkg/policies/opa/rego/aws/aws_db_instance/.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "rdsPubliclyAccessible",
"file": "rdsPubliclyAccessible.rego",
"ruleTemplate": "rdsPubliclyAccessible",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "HIGH",
"description": "RDS Instance publicly_accessible flag is true",
"ruleReferenceId": "",
"category": "Data Security",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package accurics

{{.prefix}}rdsPubliclyAccessible[retVal] {
db := input.aws_db_instance[_]
db.config.publicly_accessible == true
traverse = "publicly_accessible"
retVal := { "Id": db.id, "ReplaceType": "edit", "CodeType": "attribute", "Traverse": traverse, "Attribute": "publicly_accessible", "AttributeDataType": "bool", "Expected": false, "Actual": db.config.publicly_accessible }
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"ruleName": "noAccessKeyForRootAccount",
"file": "noAccessKeyForRootAccount.rego",
"ruleTemplate": "noAccessKeyForRootAccount",
"ruleTemplateArgs": {
"prefix": ""
},
"severity": "HIGH",
"description": "The root account is the most privileged user in an AWS account. AWS Access Keys provide programmatic access to a given AWS account. It is recommended that all access keys associated with the root account be removed. Removing access keys associated with the root account limits vectors by which the account can be compromised. Additionally, removing the root access keys encourages the creation and use of role based accounts that are least privileged.",
"ruleReferenceId": "AWS.IamUser.IAM.High.0390",
"category": "Identity and Access Management",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package accurics

{{.prefix}}noAccessKeyForRootAccount[retVal] {
access := input.aws_iam_access_key[_]
access.type == "aws_iam_access_key"
status = getStatus(access.config)
status == "Active"
access.config.user == "root"
traverse = "status"
retVal := { "Id": access.id, "ReplaceType": "edit", "CodeType": "attribute", "Traverse": traverse, "Attribute": "status", "AttributeDataType": "string", "Expected": "Inactive", "Actual": access.config.status }
}

getStatus(config) = "Active" {
# defaults to Active
not config.status
}

getStatus(config) = "Active" {
config.status == "Active"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"ruleName": "passwordRotateEvery90Days",
"file": "passwordRotateEvery90Days.rego",
"ruleTemplate": "passwordRotateEvery90Days",
"ruleTemplateArgs": {
"name": "passwordRotateEvery90Days",
"prefix": ""
},
"severity": "LOW",
"description": "Reducing the password lifetime increases account resiliency against brute force login attempts",
"ruleReferenceId": "AWS.Iam.IAM.Low.0540",
"category": "IAM",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"ruleName": "passwordRequireLowerCase",
"file": "passwordPolicyRequirement.rego",
"ruleTemplate": "passwordRequireLowerCase",
"ruleTemplateArgs": {
"name": "passwordRequireLowerCase",
"prefix": "",
"required_parameter": "require_lowercase_characters"
},
"severity": "MEDIUM",
"description": "Lower case alphabet not present in the Password, Password Complexity is not high. Increased Password complexity increases resiliency against brute force attack",
"ruleReferenceId": "AWS.Iam.IAM.Medium.0454",
"category": "IAM",
"version": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"ruleName": "passwordRequireNumber",
"file": "passwordPolicyRequirement.rego",
"ruleTemplate": "passwordRequireNumber",
"ruleTemplateArgs": {
"name": "passwordRequireNumber",
"prefix": "",
"required_parameter": "require_numbers"
},
"severity": "MEDIUM",
"description": "Number not present in the Password, Password Complexity is not high. Increased Password complexity increases resiliency against brute force attack",
"ruleReferenceId": "AWS.Iam.IAM.Medium.0455",
"category": "IAM",
"version": 2
}
Loading

0 comments on commit 9331bf2

Please sign in to comment.