Skip to content

Commit 1549b5a

Browse files
committed
Upgrade plugin to use new abstractions
1 parent e466aca commit 1549b5a

3 files changed

Lines changed: 59 additions & 156 deletions

File tree

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,17 @@ module github.com/compliance-framework/plugin-aws-networking-security
33
go 1.23.2
44

55
require (
6-
github.com/aws/aws-sdk-go-v2 v1.36.3
76
github.com/aws/aws-sdk-go-v2/config v1.29.9
87
github.com/aws/aws-sdk-go-v2/service/ec2 v1.208.0
9-
github.com/compliance-framework/agent v0.1.1
10-
github.com/compliance-framework/configuration-service v0.1.1
11-
github.com/google/uuid v1.6.0
8+
github.com/compliance-framework/agent v0.1.7
129
github.com/hashicorp/go-hclog v1.5.0
1310
github.com/hashicorp/go-plugin v1.6.2
14-
google.golang.org/protobuf v1.35.2
1511
)
1612

1713
require (
1814
github.com/OneOfOne/xxhash v1.2.8 // indirect
1915
github.com/agnivade/levenshtein v1.2.0 // indirect
16+
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
2017
github.com/aws/aws-sdk-go-v2/credentials v1.17.62 // indirect
2118
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
2219
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
@@ -30,13 +27,15 @@ require (
3027
github.com/aws/smithy-go v1.22.2 // indirect
3128
github.com/beorn7/perks v1.0.1 // indirect
3229
github.com/cespare/xxhash/v2 v2.3.0 // indirect
30+
github.com/compliance-framework/configuration-service v0.1.2-0.20250327060646-625c895cd99c // indirect
3331
github.com/fatih/color v1.15.0 // indirect
3432
github.com/go-ini/ini v1.67.0 // indirect
3533
github.com/go-logr/logr v1.4.2 // indirect
3634
github.com/go-logr/stdr v1.2.2 // indirect
3735
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
3836
github.com/gobwas/glob v0.2.3 // indirect
3937
github.com/golang/protobuf v1.5.4 // indirect
38+
github.com/google/uuid v1.6.0 // indirect
4039
github.com/gorilla/mux v1.8.1 // indirect
4140
github.com/hashicorp/yamux v0.1.1 // indirect
4241
github.com/mattn/go-colorable v0.1.13 // indirect
@@ -65,6 +64,7 @@ require (
6564
golang.org/x/text v0.21.0 // indirect
6665
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
6766
google.golang.org/grpc v1.69.2 // indirect
67+
google.golang.org/protobuf v1.35.2 // indirect
6868
gopkg.in/yaml.v3 v3.0.1 // indirect
6969
sigs.k8s.io/yaml v1.4.0 // indirect
7070
)

go.sum

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
5656
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
5757
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
5858
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
59-
github.com/compliance-framework/agent v0.1.1 h1:uQ4idgwOMqrgM0JeYCtBv20HZoMymsH2nownrkl457w=
60-
github.com/compliance-framework/agent v0.1.1/go.mod h1:jy/26xgTx9+at64ipTV1oo80pTVyhtlZaSMViQ3cVVQ=
61-
github.com/compliance-framework/configuration-service v0.1.1 h1:p/r5vq1FLe0S8j/kLhth4Dvda8xajVPOBjnO9QauMjM=
62-
github.com/compliance-framework/configuration-service v0.1.1/go.mod h1:tLKJKXbQbY9Pg/e3BJtJVkqxaejXJMHoE8Yp0NW4lDE=
59+
github.com/compliance-framework/agent v0.1.7 h1:1UqJpNdrZrea9TCw9Z0bHN+I/L8Y67fl9teCGIqSU2g=
60+
github.com/compliance-framework/agent v0.1.7/go.mod h1:dAjHJecMEMdKzylOatT54tXmbjgx5d2Wsq4mGnRksZk=
61+
github.com/compliance-framework/configuration-service v0.1.2-0.20250327060646-625c895cd99c h1:7RIDZy+OcF/9O5EquFchd0W9TY+mlz2zSCVCsReG8Bw=
62+
github.com/compliance-framework/configuration-service v0.1.2-0.20250327060646-625c895cd99c/go.mod h1:tLKJKXbQbY9Pg/e3BJtJVkqxaejXJMHoE8Yp0NW4lDE=
6363
github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA=
6464
github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
6565
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
@@ -348,5 +348,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
348348
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
349349
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
350350
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
351+
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
352+
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
351353
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
352354
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

main.go

Lines changed: 48 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,16 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"github.com/compliance-framework/plugin-aws-networking-security/internal"
8-
"os"
9-
"time"
10-
117
"github.com/aws/aws-sdk-go-v2/config"
128
"github.com/aws/aws-sdk-go-v2/service/ec2"
139
policyManager "github.com/compliance-framework/agent/policy-manager"
1410
"github.com/compliance-framework/agent/runner"
1511
"github.com/compliance-framework/agent/runner/proto"
16-
"github.com/compliance-framework/configuration-service/sdk"
17-
"github.com/google/uuid"
12+
"github.com/compliance-framework/plugin-aws-networking-security/internal"
1813
"github.com/hashicorp/go-hclog"
1914
goplugin "github.com/hashicorp/go-plugin"
20-
"google.golang.org/protobuf/types/known/timestamppb"
15+
"os"
16+
"slices"
2117
)
2218

2319
type CompliancePlugin struct {
@@ -37,7 +33,6 @@ func (l *CompliancePlugin) Configure(req *proto.ConfigureRequest) (*proto.Config
3733

3834
func (l *CompliancePlugin) Eval(request *proto.EvalRequest, apiHelper runner.ApiHelper) (*proto.EvalResponse, error) {
3935
ctx := context.TODO()
40-
startTime := time.Now()
4136
evalStatus := proto.ExecutionStatus_SUCCESS
4237
var accumulatedErrors error
4338

@@ -64,18 +59,22 @@ func (l *CompliancePlugin) Eval(request *proto.EvalRequest, apiHelper runner.Api
6459
findings := make([]*proto.Finding, 0)
6560
observations := make([]*proto.Observation, 0)
6661

67-
subjectAttributeMap := map[string]string{
68-
"type": "aws",
69-
"service": "security-group",
70-
"instance-id": *group.GroupId,
71-
"instance-name": *group.GroupName,
72-
"vpc-id": *group.VpcId,
62+
labels := map[string]string{
63+
"type": "aws",
64+
"service": "security-groups",
65+
"instance-id": *group.GroupId,
7366
}
7467
subjects := []*proto.SubjectReference{
7568
{
76-
Type: "aws-security-group",
77-
Attributes: subjectAttributeMap,
78-
Title: internal.StringAddressed("AWS Security Group"),
69+
Type: "aws-security-group",
70+
Attributes: map[string]string{
71+
"type": "aws",
72+
"service": "security-group",
73+
"instance-id": *group.GroupId,
74+
"instance-name": *group.GroupName,
75+
"vpc-id": *group.VpcId,
76+
},
77+
Title: internal.StringAddressed("AWS Security Group"),
7978
Props: []*proto.Property{
8079
{
8180
Name: "security-group-id",
@@ -87,6 +86,21 @@ func (l *CompliancePlugin) Eval(request *proto.EvalRequest, apiHelper runner.Api
8786
},
8887
},
8988
},
89+
{
90+
Type: "aws-vpc",
91+
Attributes: map[string]string{
92+
"type": "aws",
93+
"service": "vpc",
94+
"vpc-id": fmt.Sprintf("%v", *group.VpcId),
95+
},
96+
Title: internal.StringAddressed("AWS VPC"),
97+
Props: []*proto.Property{
98+
{
99+
Name: "vpc-id",
100+
Value: fmt.Sprintf("%v", *group.VpcId),
101+
},
102+
},
103+
},
90104
}
91105
actors := []*proto.OriginActor{
92106
{
@@ -119,138 +133,25 @@ func (l *CompliancePlugin) Eval(request *proto.EvalRequest, apiHelper runner.Api
119133
}
120134

121135
for _, policyPath := range request.GetPolicyPaths() {
122-
steps := make([]*proto.Step, 0)
123-
steps = append(steps, &proto.Step{
124-
Title: "Compile policy bundle",
125-
Description: "Using a locally addressable policy path, compile the policy files to an in memory executable.",
126-
})
127-
steps = append(steps, &proto.Step{
128-
Title: "Execute policy bundle",
129-
Description: "Using previously collected JSON-formatted Security Group configuration, execute the compiled policies",
130-
})
131-
132-
results, err := policyManager.New(ctx, l.logger, policyPath).Execute(ctx, "compliance_plugin", map[string]interface{}{
133-
"SecurityGroupID": *group.GroupId,
134-
"IpPermissions": group.IpPermissions,
135-
"IpPermissionsEgress": group.IpPermissionsEgress,
136-
})
136+
// Explicitly reset steps to make things readable
137+
processor := policyManager.NewPolicyProcessor(
138+
l.logger,
139+
internal.MergeMaps(
140+
labels,
141+
map[string]string{
142+
"_policy_path": policyPath,
143+
},
144+
),
145+
subjects,
146+
components,
147+
actors,
148+
activities,
149+
)
150+
obs, finds, err := processor.GenerateResults(ctx, policyPath, group)
151+
observations = slices.Concat(observations, obs)
152+
findings = slices.Concat(findings, finds)
137153
if err != nil {
138-
l.logger.Error("policy evaluation failed", "error", err)
139-
evalStatus = proto.ExecutionStatus_FAILURE
140154
accumulatedErrors = errors.Join(accumulatedErrors, err)
141-
continue
142-
}
143-
144-
activities = append(activities, &proto.Activity{
145-
Title: "Execute policy",
146-
Description: "Prepare and compile policy bundles, and execute them using the prepared Security Group data",
147-
Steps: steps,
148-
})
149-
150-
for _, result := range results {
151-
// Observation UUID should differ for each individual subject, but remain consistent when validating the same policy for the same subject.
152-
// This acts as an identifier to show the history of an observation.
153-
observationUUIDMap := internal.MergeMaps(subjectAttributeMap, map[string]string{
154-
"type": "observation",
155-
"policy": result.Policy.Package.PurePackage(),
156-
"policy_file": result.Policy.File,
157-
"policy_path": policyPath,
158-
})
159-
observationUUID, err := sdk.SeededUUID(observationUUIDMap)
160-
if err != nil {
161-
accumulatedErrors = errors.Join(accumulatedErrors, err)
162-
// We've been unable to do much here, but let's try the next one regardless.
163-
continue
164-
}
165-
166-
// Finding UUID should differ for each individual subject, but remain consistent when validating the same policy for the same subject.
167-
// This acts as an identifier to show the history of a finding.
168-
findingUUIDMap := internal.MergeMaps(subjectAttributeMap, map[string]string{
169-
"type": "finding",
170-
"policy": result.Policy.Package.PurePackage(),
171-
"policy_file": result.Policy.File,
172-
"policy_path": policyPath,
173-
})
174-
findingUUID, err := sdk.SeededUUID(findingUUIDMap)
175-
if err != nil {
176-
accumulatedErrors = errors.Join(accumulatedErrors, err)
177-
// We've been unable to do much here, but let's try the next one regardless.
178-
continue
179-
}
180-
181-
observation := proto.Observation{
182-
ID: uuid.New().String(),
183-
UUID: observationUUID.String(),
184-
Collected: timestamppb.New(startTime),
185-
Expires: timestamppb.New(startTime.Add(24 * time.Hour)),
186-
Origins: []*proto.Origin{{Actors: actors}},
187-
Subjects: subjects,
188-
Activities: activities,
189-
Components: components,
190-
RelevantEvidence: []*proto.RelevantEvidence{
191-
{
192-
Description: fmt.Sprintf("Policy %v was executed against the AWS Security Group configuration, using the Local AWS Security Group Plugin", result.Policy.Package.PurePackage()),
193-
},
194-
},
195-
}
196-
197-
newFinding := func() *proto.Finding {
198-
return &proto.Finding{
199-
ID: uuid.New().String(),
200-
UUID: findingUUID.String(),
201-
Collected: timestamppb.New(time.Now()),
202-
Labels: map[string]string{
203-
"type": "aws",
204-
"service": "security-groups",
205-
"instance-id": *group.GroupId,
206-
"instance-name": *group.GroupName,
207-
"vpc-id": *group.VpcId,
208-
"_policy": result.Policy.Package.PurePackage(),
209-
"_policy_path": result.Policy.File,
210-
},
211-
Origins: []*proto.Origin{{Actors: actors}},
212-
Subjects: subjects,
213-
Components: components,
214-
RelatedObservations: []*proto.RelatedObservation{{ObservationUUID: observation.ID}},
215-
Controls: nil,
216-
}
217-
}
218-
219-
// There are no violations reported from the policies.
220-
// We'll send the observation back to the agent
221-
if len(result.Violations) == 0 {
222-
observation.Title = internal.StringAddressed("The plugin succeeded. No compliance issues to report.")
223-
observation.Description = "The plugin policies did not return any violations. The configuration is in compliance with policies."
224-
observations = append(observations, &observation)
225-
226-
finding := newFinding()
227-
finding.Title = fmt.Sprintf("No violations found on %s", result.Policy.Package.PurePackage())
228-
finding.Description = fmt.Sprintf("No violations were found on the %s policy within the AWS Security Groups Compliance Plugin.", result.Policy.Package.PurePackage())
229-
finding.Status = &proto.FindingStatus{
230-
State: runner.FindingTargetStatusSatisfied,
231-
}
232-
findings = append(findings, finding)
233-
continue
234-
}
235-
236-
// There are violations in the policy checks.
237-
// We'll send these observations back to the agent
238-
if len(result.Violations) > 0 {
239-
observation.Title = internal.StringAddressed(fmt.Sprintf("Validation on %s failed.", result.Policy.Package.PurePackage()))
240-
observation.Description = fmt.Sprintf("Observed %d violation(s) on the %s policy within the AWS Security groups Compliance Plugin.", len(result.Violations), result.Policy.Package.PurePackage())
241-
observations = append(observations, &observation)
242-
243-
for _, violation := range result.Violations {
244-
finding := newFinding()
245-
finding.Title = violation.Title
246-
finding.Description = violation.Description
247-
finding.Remarks = internal.StringAddressed(violation.Remarks)
248-
finding.Status = &proto.FindingStatus{
249-
State: runner.FindingTargetStatusNotSatisfied,
250-
}
251-
findings = append(findings, finding)
252-
}
253-
}
254155
}
255156
}
256157

0 commit comments

Comments
 (0)