Skip to content

Commit

Permalink
Merge pull request #75 from salsadigitalauorg/feature/DEVOPS-713-2fa-…
Browse files Browse the repository at this point in the history
…enforcement

[DEVOPS-713] Implement remediation for Config V2
  • Loading branch information
yusufhm authored Feb 12, 2025
2 parents e8962e9 + 2046c24 commit 9bf11e6
Show file tree
Hide file tree
Showing 61 changed files with 1,241 additions and 318 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
with:
name: build
path: build
if: github.ref_name == 'main'
if: github.ref_name == '1.x'

publish-binary:
needs: test-build
Expand Down
13 changes: 13 additions & 0 deletions cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var (
enableEnvResolver bool
breachTypes []string
plugins []string
names []string
)

func main() {
Expand Down Expand Up @@ -61,6 +62,17 @@ func main() {
}
gen.AnalysePlugin(plugins)
break
case "remediator":
if len(plugins) == 0 {
log.Fatal("remediator missing flags; plugins is required")
}
if len(names) == 0 {
log.Fatal("remediator missing flags; name is required")
}
gen.RemediatorPlugin(plugins, names)
break
default:
log.Fatalf("unknown argument '%s'", arg)
}
}

Expand All @@ -70,6 +82,7 @@ func parseFlags() {
pflag.BoolVar(&enableEnvResolver, "envresolver", false, "Add envResolver methods to the plugin")
pflag.StringSliceVar(&breachTypes, "type", []string{}, "The breach type")
pflag.StringSliceVar(&plugins, "plugin", []string{}, "The plugin struct")
pflag.StringSliceVar(&names, "name", []string{}, "The plugin name")
pflag.Parse()
}

Expand Down
65 changes: 9 additions & 56 deletions cmd/gen/breachtype.go
Original file line number Diff line number Diff line change
@@ -1,77 +1,30 @@
package gen

import (
"bytes"
"log"
"os"
"path/filepath"
"strings"
"text/template"
)

func BreachType(breachTypes []string) {
log.Println("Generating breach type funcs -", strings.Join(breachTypes, ","))

tmplPath := filepath.Join("..", "..", "pkg", "breach", "gen_templates", "breachtype.go.tmpl")
tmplTestPath := filepath.Join("..", "..", "pkg", "breach", "gen_templates", "breachtype_test.go.tmpl")

breachTypeFile := "breach_gen.go"
breachTypeFullFilePath := filepath.Join(getScriptPath(), "..", "..", "pkg", "breach", breachTypeFile)
if err := os.Remove(breachTypeFullFilePath); err != nil && !os.IsNotExist(err) {
log.Fatalln(err)
}
createFileWithString(breachTypeFullFilePath, "package breach\n")

for _, bt := range breachTypes {
appendFileContent(breachTypeFullFilePath, breachTypeFuncs(bt))
}
}

func breachTypeFuncs(bt string) string {
tmplStr := `
/*
* {{.BreachType}}Breach
*/
func (b *{{.BreachType}}Breach) GetCheckName() string {
return b.CheckName
}
func (b *{{.BreachType}}Breach) GetCheckType() string {
return b.CheckType
}
func (b *{{.BreachType}}Breach) GetRemediation() *Remediation {
return &b.Remediation
}
func (b *{{.BreachType}}Breach) GetSeverity() string {
return b.Severity
}
func (b *{{.BreachType}}Breach) GetType() BreachType {
return BreachType{{.BreachType}}
}
func (b *{{.BreachType}}Breach) SetCommonValues(checkType string, checkName string, severity string) {
b.BreachType = b.GetType()
b.CheckType = checkType
b.CheckName = checkName
b.Severity = severity
}
func (b *{{.BreachType}}Breach) SetRemediation(status RemediationStatus, msg string) {
b.Remediation.Status = status
if msg != "" {
b.Remediation.Messages = []string{msg}
}
}
`
tmpl, err := template.New("breachTypeFuncs").Parse(tmplStr)
if err != nil {
log.Fatalln(err)
}
templateToFile(tmplPath, struct{ BreachTypes []string }{breachTypes}, breachTypeFullFilePath)

buf := &bytes.Buffer{}
err = tmpl.Execute(buf, struct{ BreachType string }{bt})
if err != nil {
// Test file.
breachTypeTestFile := "breach_gen_test.go"
breachTypeFullTestFilePath := filepath.Join(getScriptPath(), "..", "..", "pkg", "breach", breachTypeTestFile)
if err := os.Remove(breachTypeFullTestFilePath); err != nil && !os.IsNotExist(err) {
log.Fatalln(err)
}
return buf.String()
templateToFile(tmplTestPath, struct{ BreachTypes []string }{breachTypes}, breachTypeFullTestFilePath)
}
28 changes: 28 additions & 0 deletions cmd/gen/remediatorplugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package gen

import (
"log"
"os"
"path/filepath"
"strings"
)

func RemediatorPlugin(plugins []string, names []string) {
log.Println("Generating remediator plugin funcs -", strings.Join(plugins, ","))

tmplPath := filepath.Join("..", "..", "pkg", "remediation", "templates", "remediatorplugin.go.tmpl")

for i, p := range plugins {
name := names[i]
pluginFile := strings.ToLower(p) + "_gen.go"
pluginFullFilePath := filepath.Join(getScriptPath(), "..", "..", "pkg", "remediation", pluginFile)
if err := os.Remove(pluginFullFilePath); err != nil && !os.IsNotExist(err) {
log.Fatalln(err)
}

templateToFile(tmplPath, struct {
Plugin string
Name string
}{Plugin: p, Name: name}, pluginFullFilePath)
}
}
10 changes: 10 additions & 0 deletions docs/src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ module.exports = {
'connections',
'collect',
'analyse',
'remediate',
'outputs',
]
}
Expand Down Expand Up @@ -109,10 +110,19 @@ module.exports = {
collapsable: false,
children: [
['/reference/analyse/allowed-list', 'allowed:list'],
['/reference/analyse/equals', 'equals'],
['/reference/analyse/not-empty', 'not:empty'],
['/reference/analyse/regex-match', 'regex:match'],
]
},
{
title: 'Remediate',
path: '/reference/remediate',
collapsable: false,
children: [
['/reference/remediate/command', 'command'],
]
},
]
}
],
Expand Down
1 change: 1 addition & 0 deletions docs/src/guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,5 @@ Global Flags:
- [Connections](connections)
- [Collecting data](collect)
- [Analysing data](analyse)
- [Remediating breaches](remediate)
- [Outputs](outputs)
2 changes: 1 addition & 1 deletion docs/src/guide/analyse.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Analysing Data
# Analysing data

## Simple string check
...
Expand Down
2 changes: 1 addition & 1 deletion docs/src/guide/collect.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Collecting Data
# Collecting data



1 change: 1 addition & 0 deletions docs/src/guide/remediate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Remediating breaches
6 changes: 6 additions & 0 deletions docs/src/reference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,11 @@ The following Collect/Fact plugins are available:

The following Analyse plugins are available:
- [allowed:list](../reference/analyse/allowed-list)
- [equals](../reference/analyse/equals)
- [not:empty](../reference/analyse/not-empty)
- [regex:match](../reference/analyse/regex-match)

## Remediation plugins

The following Remediation plugins are available:
- [command](../reference/remediate/command)
13 changes: 13 additions & 0 deletions docs/src/reference/analyse/equals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# equals

The `equals` plugin checks if a value is exactly equal to an input.

## Plugin fields

| Field | Description | Required | Default |
| ----- | -------------------------------------------------------------- | :------: | :-----: |
| value | The value to compare against. | Yes | "" |
| key | A key to look up the value when the input is a map of strings. | No | [] |


<Content :page-key="$site.pages.find(p => p.path === '/reference/common/analyse.html').key"/>
9 changes: 9 additions & 0 deletions docs/src/reference/common/analyse.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
| input | The input for the policy - used to select the fact plugin to use. | Yes | - |
| severity | The severity of the policy when breached (low, normal, high, critical) | No | normal |
| breach-format | The breach template for the policy. The table below shows the available fields. | No | Empty breach template |
| remediation | The remediation for the policy. The table below shows the available fields. | No | Empty remediation |

### Breach template

Expand All @@ -21,3 +22,11 @@ TODO: Add information on how to use go template variables.
| key | The key. | No | "" |
| value-label | The label for the value. | No | "" |
| value | The value. | No | "" |

### Remediation

| Field | Description | Required | Default |
| ------ | --------------------------------------------------------------- | :------: | :----------------------: |
| plugin | The plugin to use for remediation. | No | "command" |
| msg | The message to display when remediation completes successfully. | No | "remediation successful" |
| ... | Any fields required by the plugin. | No | - |
6 changes: 6 additions & 0 deletions docs/src/reference/common/remediate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Common fields

| Field | Description | Required | Default |
| ------ | --------------------------------------------------------------- | :------: | :----------------------: |
| plugin | The plugin to use for remediation. | No | "command" |
| msg | The message to display when remediation completes successfully. | No | "remediation successful" |
4 changes: 4 additions & 0 deletions docs/src/reference/remediate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: Remediate
---
# Remediate plugin reference
11 changes: 11 additions & 0 deletions docs/src/reference/remediate/command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# command

## Plugin fields

| Field | Description | Required | Default |
| ----- | --------------------------------- | :------: | :-----: |
| cmd | The command to run. | Yes | - |
| args | Arguments to pass to the command. | No | [] |


<Content :page-key="$site.pages.find(p => p.path === '/reference/common/remediate.html').key"/>
20 changes: 20 additions & 0 deletions examples/remediation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,23 @@ collect:
set -o pipefail
drush pm:list --no-core --package=Security --fields=name,status --format=json|jq -r '.tfa.status'
analyse:
tfa-module-absent:
equals:
description: tfa module not in codebase
input: db-tfa-module
key: stdout
value: 'null'

db-tfa-module-disabled:
equals:
description: tfa module is disabled
input: db-tfa-module
key: stdout
value: Disabled
remediation:
cmd: drush
args:
- pm:enable
- tfa
msg: tfa module has been successfully enabled
19 changes: 10 additions & 9 deletions pkg/analyse/allowedlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type AllowedList struct {
Severity string `yaml:"severity"`
breach.BreachTemplate `yaml:"breach-format"`
Result result.Result
Remediation interface{} `yaml:"remediation"`
input fact.Facter

// Plugin fields.
Expand Down Expand Up @@ -60,15 +61,15 @@ func (p *AllowedList) Analyse() {
breach.EvaluateTemplate(p, &breach.ValueBreach{
ValueLabel: "deprecated value found",
Value: v,
})
}, p.Remediation)
continue
}

if len(p.Required) == 0 && !p.isAllowed(v) {
breach.EvaluateTemplate(p, &breach.ValueBreach{
ValueLabel: "disallowed value found",
Value: v,
})
}, p.Remediation)
}

if len(p.Required) > 0 && p.isRequired(v) {
Expand All @@ -82,7 +83,7 @@ func (p *AllowedList) Analyse() {
breach.EvaluateTemplate(p, &breach.ValueBreach{
ValueLabel: "required value not found",
Value: r,
})
}, p.Remediation)
}
}
}
Expand All @@ -100,7 +101,7 @@ func (p *AllowedList) Analyse() {
Key: k,
ValueLabel: "deprecated",
Value: v,
})
}, p.Remediation)
continue
}

Expand All @@ -110,7 +111,7 @@ func (p *AllowedList) Analyse() {
Key: k,
ValueLabel: "disallowed",
Value: v,
})
}, p.Remediation)
continue
}

Expand All @@ -125,7 +126,7 @@ func (p *AllowedList) Analyse() {
breach.EvaluateTemplate(p, &breach.ValueBreach{
ValueLabel: "required value not found",
Value: r,
})
}, p.Remediation)
}
}
}
Expand All @@ -149,7 +150,7 @@ func (p *AllowedList) Analyse() {
Key: k,
ValueLabel: "deprecated",
Value: v,
})
}, p.Remediation)
continue
}

Expand All @@ -159,7 +160,7 @@ func (p *AllowedList) Analyse() {
Key: k,
ValueLabel: "disallowed",
Value: v,
})
}, p.Remediation)
continue
}

Expand All @@ -175,7 +176,7 @@ func (p *AllowedList) Analyse() {
Key: k,
ValueLabel: "required value not found",
Value: r,
})
}, p.Remediation)
}
}
}
Expand Down
Loading

0 comments on commit 9bf11e6

Please sign in to comment.