Created
December 5, 2025 14:26
-
-
Save rnaveiras/7284849ee1cd1ec6f3feddfdd7779ee7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Script to publish EmergingThreatPublished events to the events SNS topic. | |
| This script is designed to manually trigger an EmergingThreatPublished event, | |
| which will cause downstream subscribers (e.g., notification services) to process | |
| the event as if the threat had just been published through the normal flow. | |
| Required: | |
| For non-local environments, you must have AWS credentials configured | |
| (e.g., via AWS_PROFILE or SSO login). | |
| Usage: | |
| ./publish_event -threat-id=<uuid> -user-id=<uuid> -env=<environment> [-dry-run] | |
| Flags: | |
| -env string | |
| Required. Environment to run in (local, dev, pen, demo, prod) | |
| -threat-id string | |
| Required. The ID of the emerging threat to publish the event for | |
| -user-id string | |
| Required. The ID of the user who published the threat | |
| -dry-run | |
| Optional. Defaults to true. Set to false to actually publish the event | |
| -y | |
| Optional. Skip confirmation prompt | |
| Examples: | |
| # Dry run in dev environment | |
| ./publish_event -threat-id=abc123 -user-id=user456 -env=dev | |
| # Actually publish in dev environment | |
| ./publish_event -threat-id=abc123 -user-id=user456 -env=dev -dry-run=false | |
| # Publish in prod with confirmation skip | |
| ./publish_event -threat-id=abc123 -user-id=user456 -env=prod -dry-run=false -y | |
| */ | |
| package main | |
| import ( | |
| "context" | |
| "flag" | |
| "fmt" | |
| "time" | |
| "google.golang.org/protobuf/types/known/timestamppb" | |
| "riskledger.com/rl/pkg/config/common" | |
| "riskledger.com/rl/pkg/pubsub" | |
| pubsubmw "riskledger.com/rl/pkg/pubsub/middleware" | |
| "riskledger.com/rl/pkg/pubsub/snssqs" | |
| emerging_threatsv1 "riskledger.com/rl/proto/emerging_threats/v1" | |
| "riskledger.com/rl/scripts/util" | |
| ) | |
| // envConfig holds the SNS topic ARN and AWS settings for each environment. | |
| type envConfig struct { | |
| SNSTopicARN string | |
| AWSEndpoint string | |
| AWSRegion string | |
| } | |
| // getEnvConfig returns the SNS topic ARN for the given environment. | |
| func getEnvConfig(env string) (*envConfig, error) { | |
| configs := map[string]envConfig{ | |
| "local": { | |
| SNSTopicARN: "arn:aws:sns:eu-west-1:000000000000:local-events", | |
| AWSEndpoint: "http://localhost:4566", | |
| AWSRegion: "eu-west-1", | |
| }, | |
| "dev": { | |
| SNSTopicARN: "arn:aws:sns:eu-west-1:141388701384:dev-events", | |
| AWSEndpoint: "", | |
| AWSRegion: "eu-west-1", | |
| }, | |
| "pen": { | |
| SNSTopicARN: "arn:aws:sns:eu-west-1:141388701384:pen-events", | |
| AWSEndpoint: "", | |
| AWSRegion: "eu-west-1", | |
| }, | |
| "demo": { | |
| SNSTopicARN: "arn:aws:sns:eu-west-1:141388701384:demo-events", | |
| AWSEndpoint: "", | |
| AWSRegion: "eu-west-1", | |
| }, | |
| "prod": { | |
| SNSTopicARN: "arn:aws:sns:eu-west-1:141388701384:prod-events", | |
| AWSEndpoint: "", | |
| AWSRegion: "eu-west-1", | |
| }, | |
| } | |
| config, exists := configs[env] | |
| if !exists { | |
| return nil, fmt.Errorf("invalid environment: %s. Must be one of: local, dev, pen, demo, prod", env) | |
| } | |
| return &config, nil | |
| } | |
| func main() { | |
| var threatID string | |
| var userID string | |
| var environment string | |
| var dryRun bool | |
| var skipConfirmation bool | |
| var publishedAtStr string | |
| flag.StringVar(&threatID, "threat-id", "", "Required. The ID of the emerging threat") | |
| flag.StringVar(&userID, "user-id", "", "Required. The ID of the user who published the threat") | |
| flag.StringVar(&environment, "env", "", "Required. Environment (local, dev, pen, demo, prod)") | |
| flag.BoolVar(&dryRun, "dry-run", true, "Set to false to actually publish the event") | |
| flag.BoolVar(&skipConfirmation, "y", false, "Skip confirmation prompt") | |
| flag.StringVar(&publishedAtStr, "published-at", "", "Optional. Published timestamp in RFC3339 format (defaults to now)") | |
| flag.Parse() | |
| log := util.Logger() | |
| ctx := context.Background() | |
| // Validate required flags | |
| if threatID == "" { | |
| log.Error("threat-id flag is required") | |
| return | |
| } | |
| if userID == "" { | |
| log.Error("user-id flag is required") | |
| return | |
| } | |
| if environment == "" { | |
| log.Error("env flag is required") | |
| return | |
| } | |
| // Get environment config | |
| envCfg, err := getEnvConfig(environment) | |
| if err != nil { | |
| log.Error("invalid environment", "error", err) | |
| return | |
| } | |
| // Parse published_at timestamp | |
| var publishedAt time.Time | |
| if publishedAtStr != "" { | |
| publishedAt, err = time.Parse(time.RFC3339, publishedAtStr) | |
| if err != nil { | |
| log.Error("invalid published-at format, expected RFC3339", | |
| "error", err, | |
| "value", publishedAtStr, | |
| ) | |
| return | |
| } | |
| } else { | |
| publishedAt = time.Now() | |
| } | |
| log.Info("preparing to publish EmergingThreatPublished event", | |
| "threat_id", threatID, | |
| "user_id", userID, | |
| "published_at", publishedAt.Format(time.RFC3339), | |
| "environment", environment, | |
| "sns_topic_arn", envCfg.SNSTopicARN, | |
| "dry_run", dryRun, | |
| ) | |
| if !dryRun && !skipConfirmation { | |
| if !util.PromptForConfirmation("This will publish an EmergingThreatPublished event to SNS. Continue?") { | |
| log.Info("Operation cancelled by user") | |
| return | |
| } | |
| } | |
| if dryRun { | |
| log.Info("dry run: would publish EmergingThreatPublished event", | |
| "threat_id", threatID, | |
| "user_id", userID, | |
| "published_at", publishedAt.Format(time.RFC3339), | |
| "sns_topic_arn", envCfg.SNSTopicARN, | |
| ) | |
| return | |
| } | |
| // Load AWS config | |
| awsConfig := common.AWS{ | |
| Region: envCfg.AWSRegion, | |
| AWSEndpoint: envCfg.AWSEndpoint, | |
| } | |
| awsV2Config, err := awsConfig.LoadConfig(ctx) | |
| if err != nil { | |
| log.Error("failed to load AWS config", "error", err) | |
| return | |
| } | |
| // create the SNS publisher using the snssqs driver | |
| pubmw := pubsubmw.PublishDefaults(log, "emerging threats publish event script") | |
| eventsPub := pubsub.NewPub(snssqs.NewSender(awsV2Config, envCfg.SNSTopicARN), log, pubmw) | |
| defer eventsPub.Stop() | |
| // create the event | |
| event := &emerging_threatsv1.EmergingThreatPublishedEvent{ | |
| Id: threatID, | |
| PublishedBy: userID, | |
| PublishedAt: timestamppb.New(publishedAt), | |
| } | |
| // publish the event | |
| err = eventsPub.Publish(ctx, "EmergingThreatPublished", event) | |
| if err != nil { | |
| log.Error("failed to publish event", "error", err) | |
| return | |
| } | |
| log.Info("EmergingThreatPublished event published successfully", | |
| "threat_id", threatID, | |
| "user_id", userID, | |
| "published_at", publishedAt.Format(time.RFC3339), | |
| "environment", environment, | |
| "sns_topic_arn", envCfg.SNSTopicARN, | |
| ) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment