@@ -2,10 +2,14 @@ package postmark
22
33import (
44 "context"
5- regexp "github.com/wasilibs/go-re2"
5+ "errors"
6+ "fmt"
7+ "io"
68 "net/http"
79 "strings"
810
11+ regexp "github.com/wasilibs/go-re2"
12+
913 "github.com/trufflesecurity/trufflehog/v3/pkg/common"
1014 "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
1115 "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
@@ -43,20 +47,10 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
4347 }
4448
4549 if verify {
46- req , err := http .NewRequestWithContext (ctx , "GET" , "https://api.postmarkapp.com/deliverystats" , nil )
47- if err != nil {
48- continue
49- }
50- req .Header .Add ("Accept" , "application/json" )
51- req .Header .Add ("Content-Type" , "application/json" )
52- req .Header .Add ("X-Postmark-Server-Token" , resMatch )
53- res , err := client .Do (req )
54- if err == nil {
55- defer res .Body .Close ()
56- if res .StatusCode >= 200 && res .StatusCode < 300 {
57- s1 .Verified = true
58- }
59- }
50+ valid , extraData , err := verifyKey (ctx , client , resMatch )
51+ s1 .Verified = valid
52+ s1 .ExtraData = extraData
53+ s1 .SetVerificationError (err )
6054 }
6155
6256 results = append (results , s1 )
@@ -65,6 +59,87 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
6559 return results , nil
6660}
6761
62+ // verifyKey verifies a Postmark key by making requests to the Postmark API.
63+ // It tries both server and account API key verification.
64+ func verifyKey (ctx context.Context , client * http.Client , key string ) (bool , map [string ]string , error ) {
65+ errs := make ([]error , 0 , 2 )
66+
67+ // Try verifying as server API key first
68+ valid , err := verifyServerAPIKey (ctx , client , key )
69+ if valid {
70+ // If valid as server API key, return immediately
71+ return true , map [string ]string {"type" : "server" }, nil
72+ }
73+ if err != nil {
74+ errs = append (errs , err )
75+ }
76+
77+ // Try verifying as account API key next
78+ valid , err = verifyAccountAPIKey (ctx , client , key )
79+ if valid {
80+ // If valid as account API key, return immediately
81+ return true , map [string ]string {"type" : "account" }, nil
82+ }
83+ if err != nil {
84+ errs = append (errs , err )
85+ }
86+ if len (errs ) > 0 {
87+ // If there were errors during verification, return them
88+ return false , nil , errors .Join (errs ... )
89+ }
90+ return false , nil , nil
91+ }
92+
93+ // verifyServerAPIKey verifies a Postmark server API key by making a request to the Postmark API.
94+ func verifyServerAPIKey (ctx context.Context , client * http.Client , key string ) (bool , error ) {
95+ return verifyKeyWithOptions (
96+ ctx ,
97+ client ,
98+ key ,
99+ "/deliverystats" ,
100+ "X-Postmark-Server-Token" ,
101+ )
102+ }
103+
104+ // verifyAccountAPIKey verifies a Postmark account API key by making a request to the Postmark API.
105+ func verifyAccountAPIKey (ctx context.Context , client * http.Client , key string ) (bool , error ) {
106+ return verifyKeyWithOptions (
107+ ctx ,
108+ client ,
109+ key ,
110+ "/domains?count=10&offset=0" ,
111+ "X-Postmark-Account-Token" ,
112+ )
113+ }
114+
115+ // verifyKeyWithOptions is a generic function to verify a Postmark key with given endpoint and header.
116+ func verifyKeyWithOptions (ctx context.Context , client * http.Client , key , endpoint , authHeader string ) (bool , error ) {
117+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , "https://api.postmarkapp.com" + endpoint , nil )
118+ if err != nil {
119+ return false , err
120+ }
121+ req .Header .Add ("Accept" , "application/json" )
122+ req .Header .Add ("Content-Type" , "application/json" )
123+ req .Header .Add (authHeader , key )
124+ res , err := client .Do (req )
125+ if err != nil {
126+ return false , err
127+ }
128+ defer func () {
129+ _ , _ = io .Copy (io .Discard , res .Body )
130+ _ = res .Body .Close ()
131+ }()
132+
133+ switch res .StatusCode {
134+ case http .StatusOK :
135+ return true , nil
136+ case http .StatusUnauthorized :
137+ return false , nil
138+ default :
139+ return false , fmt .Errorf ("unexpected status code: %d" , res .StatusCode )
140+ }
141+ }
142+
68143func (s Scanner ) Type () detectorspb.DetectorType {
69144 return detectorspb .DetectorType_Postmark
70145}
0 commit comments