Skip to content

Commit 66ef489

Browse files
authored
Merge pull request #3 from cruxstack/dev
feat: improve slack messages
2 parents e2c9dfa + 204ed31 commit 66ef489

5 files changed

Lines changed: 53 additions & 27 deletions

File tree

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ cd dist && zip deployment.zip bootstrap && cd ..
5050

5151
## Optional Environment Variables
5252

53-
| name | example | purpose | default |
54-
| --------------------------- | ------------------------------------------ | ------------------------------------------------------------ | --------------------------------- |
55-
| `APP_DEBUG_ENABLED` | `true` | verbose logging & event dump | `false` |
56-
| `APP_AWS_CONSOLE_URL` | `https://console.aws.amazon.com` | base AWS console URL | `https://console.aws.amazon.com` |
57-
| `APP_AWS_ACCESS_PORTAL_URL` | `https://myorg.awsapps.com/start` | AWS access portal URL (for federated access) | _(none - direct console links)_ |
58-
| `APP_AWS_ACCESS_ROLE_NAME` | `SecurityAuditor` | IAM role name for access portal | _(none - direct console links)_ |
53+
| name | example | purpose | default |
54+
| ------------------------------ | ------------------------------------------ | ------------------------------------------------------------ | --------------------------------- |
55+
| `APP_DEBUG_ENABLED` | `true` | verbose logging & event dump | `false` |
56+
| `APP_AWS_CONSOLE_URL` | `https://console.aws.amazon.com` | base AWS console URL | `https://console.aws.amazon.com` |
57+
| `APP_AWS_ACCESS_PORTAL_URL` | `https://myorg.awsapps.com/start` | AWS access portal URL (for federated access) | _(none - direct console links)_ |
58+
| `APP_AWS_ACCESS_ROLE_NAME` | `SecurityAuditor` | IAM role name for access portal | _(none - direct console links)_ |
59+
| `APP_AWS_SECURITYHUBV2_REGION` | `us-east-1` | AWS region for centralized SecurityHub v2 if applicable | _(none - direct console links)_ |
5960

6061
## Create Lambda Function
6162

internal/app/app.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (a *App) Process(evt awsEvent.CloudWatchEvent) error {
4646
if err != nil || !e.IsAlertable() {
4747
return err
4848
}
49-
m0, m1 := e.SlackMessage(a.Config.AwsConsoleURL, a.Config.AwsAccessPortalURL, a.Config.AwsAccessRoleName)
49+
m0, m1 := e.SlackMessage(a.Config.AwsConsoleURL, a.Config.AwsAccessPortalURL, a.Config.AwsAccessRoleName, a.Config.AWSSecurityHubv2Region)
5050
_, _, err = a.SlackClient.PostMessage(a.Config.SlackChannel, m0, m1)
5151
return err
5252
}

internal/app/config.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,26 @@ import (
88
)
99

1010
type Config struct {
11-
DebugEnabled bool
12-
AwsConsoleURL string
13-
AwsAccessPortalURL string
14-
AwsAccessRoleName string
15-
SlackToken string
16-
SlackChannel string
11+
DebugEnabled bool
12+
AwsConsoleURL string
13+
AwsAccessPortalURL string
14+
AwsAccessRoleName string
15+
AWSSecurityHubv2Region string
16+
SlackToken string
17+
SlackChannel string
1718
}
1819

1920
func NewConfig() (*Config, error) {
2021
debugEnabled, _ := strconv.ParseBool(os.Getenv("APP_DEBUG_ENABLED"))
2122

2223
cfg := Config{
23-
DebugEnabled: debugEnabled,
24-
AwsConsoleURL: os.Getenv("APP_AWS_CONSOLE_URL"),
25-
AwsAccessPortalURL: os.Getenv("APP_AWS_ACCESS_PORTAL_URL"),
26-
AwsAccessRoleName: os.Getenv("APP_AWS_ACCESS_ROLE_NAME"),
27-
SlackToken: os.Getenv("APP_SLACK_TOKEN"),
28-
SlackChannel: os.Getenv("APP_SLACK_CHANNEL"),
24+
DebugEnabled: debugEnabled,
25+
AwsConsoleURL: os.Getenv("APP_AWS_CONSOLE_URL"),
26+
AwsAccessPortalURL: os.Getenv("APP_AWS_ACCESS_PORTAL_URL"),
27+
AwsAccessRoleName: os.Getenv("APP_AWS_ACCESS_ROLE_NAME"),
28+
AWSSecurityHubv2Region: os.Getenv("APP_AWS_SECURITYHUBV2_REGION"),
29+
SlackToken: os.Getenv("APP_SLACK_TOKEN"),
30+
SlackChannel: os.Getenv("APP_SLACK_CHANNEL"),
2931
}
3032

3133
if cfg.AwsConsoleURL == "" {

internal/events/events.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ import (
66

77
type SecurityHubEvent interface {
88
IsAlertable() bool
9-
SlackMessage(consoleURL, accessPortalURL, accessRoleName string) (slack.MsgOption, slack.MsgOption)
9+
SlackMessage(consoleURL, accessPortalURL, accessRoleName, shRegion string) (slack.MsgOption, slack.MsgOption)
1010
}

internal/events/finding.go

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ type ResourceTag struct {
135135
Value string `json:"value"`
136136
}
137137

138-
func (shf *SecurityHubV2Finding) SlackMessage(consoleURL, accessPortalURL, accessRoleName string) (slack.MsgOption, slack.MsgOption) {
138+
func (shf *SecurityHubV2Finding) SlackMessage(consoleURL, accessPortalURL, accessRoleName, shRegion string) (slack.MsgOption, slack.MsgOption) {
139139
var blocks []slack.Block
140140

141141
severityEmoji := shf.GetSeverityEmoji()
@@ -161,6 +161,12 @@ func (shf *SecurityHubV2Finding) SlackMessage(consoleURL, accessPortalURL, acces
161161
details := slack.NewSectionBlock(nil, detailFields, nil)
162162
blocks = append(blocks, details)
163163

164+
findingIDSection := slack.NewSectionBlock(
165+
slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Finding ID*\n`%s`", shf.Metadata.UID), false, false),
166+
nil, nil,
167+
)
168+
blocks = append(blocks, findingIDSection)
169+
164170
if len(shf.Resources) > 0 {
165171
resource := shf.Resources[0]
166172
var resourceFields []*slack.TextBlockObject
@@ -192,7 +198,7 @@ func (shf *SecurityHubV2Finding) SlackMessage(consoleURL, accessPortalURL, acces
192198
blocks = append(blocks, remediationSection)
193199
}
194200

195-
consoleUrl := shf.BuildConsoleUrl(consoleURL, accessPortalURL, accessRoleName)
201+
consoleUrl := shf.BuildConsoleUrl(consoleURL, accessPortalURL, accessRoleName, shRegion)
196202
buttonSection := slack.NewActionBlock(
197203
"actions",
198204
slack.NewButtonBlockElement(
@@ -270,13 +276,30 @@ func (shf *SecurityHubV2Finding) GetSeverityEmoji() string {
270276
}
271277
}
272278

273-
func (shf *SecurityHubV2Finding) BuildConsoleUrl(consoleURL, accessPortalURL, accessRoleName string) string {
274-
encodedId := url.QueryEscape(shf.FindingInfo.UID)
275-
region := shf.Cloud.Region
279+
func (shf *SecurityHubV2Finding) BuildConsoleUrl(consoleURL, accessPortalURL, accessRoleName, shRegion string) string {
280+
region := shRegion
281+
if region == "" {
282+
region = shf.Cloud.Region
283+
}
284+
285+
var view string
286+
findingType := shf.GetFindingCategory()
287+
288+
switch findingType {
289+
case "Exposure":
290+
view = "exposure"
291+
case "Posture Management":
292+
view = "postureManagement"
293+
case "Threats":
294+
view = "threats"
295+
case "Vulnerabilities":
296+
view = "vulnerabilities"
297+
}
276298

299+
// https://883776786067-fwrss4sa.us-east-1.console.aws.amazon.com/securityhub/v2/home?region=us-east-1#/postureManagement?findingDetailId=b864b75ebfd1bf2a9c0353af5a446dd521ca0af231d56d671311494ecdcedbb8&detailPanelTabId=Resources
277300
dst := fmt.Sprintf(
278-
"%s/securityhub/home?region=%s#/findings?search=Id%%3D%%255Coperator%%255C%%253AEQUALS%%255C%%253A%s",
279-
consoleURL, region, encodedId,
301+
"%s/securityhub/v2/home?region=%s#/%s?findingDetailId=%s",
302+
consoleURL, region, view, shf.Metadata.UID,
280303
)
281304

282305
if accessPortalURL != "" && accessRoleName != "" {

0 commit comments

Comments
 (0)