@@ -13,6 +13,7 @@ import (
1313)
1414
1515const testHash = "1434154969cb663afc5a73393b84cc31a1319ab6c65c9766fadd0c86bb59ef37"
16+ const testKMSKey = "aabbccddeeff00112233445566778899"
1617
1718func TestPolicyMatchAllowsSharedComposeHashPerIdentity (t * testing.T ) {
1819 policy := mustPolicy (t , `{
@@ -111,6 +112,41 @@ func TestPolicyMatchesDeclaredPeerID(t *testing.T) {
111112 }
112113}
113114
115+ func TestPolicyNormalizesKMSKeyProvider (t * testing.T ) {
116+ policy := mustPolicy (t , `{
117+ "cluster": "demo",
118+ "policy_epoch": 1,
119+ "kms": {"name": "KMS", "id": "0x` + testKMSKey + `"},
120+ "workloads": [{
121+ "workload_id": "demo/worker/0/webdemo",
122+ "identity": "spiffe://demo/webdemo",
123+ "consul_service": "webdemo",
124+ "allowed_compose_hashes": ["` + testHash + `"]
125+ }]
126+ }` )
127+
128+ if policy .KMS == nil {
129+ t .Fatal ("kms policy was not parsed" )
130+ }
131+ if policy .KMS .Name != "kms" {
132+ t .Fatalf ("wrong kms name: %s" , policy .KMS .Name )
133+ }
134+ if policy .KMS .ID != testKMSKey {
135+ t .Fatalf ("wrong kms id: %s" , policy .KMS .ID )
136+ }
137+ }
138+
139+ func TestDecodeKeyProviderInfo (t * testing.T ) {
140+ raw := hex .EncodeToString ([]byte (`{"name":"kms","id":"0x` + testKMSKey + `"}` ))
141+ got , err := decodeKeyProviderInfo (raw )
142+ if err != nil {
143+ t .Fatal (err )
144+ }
145+ if got .Name != "kms" || got .ID != testKMSKey {
146+ t .Fatalf ("wrong key provider: %+v" , got )
147+ }
148+ }
149+
114150func TestReportDataHexBindsStatementAndNonce (t * testing.T ) {
115151 binding := "abcd"
116152 nonce := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
@@ -144,7 +180,11 @@ func TestAttestFlow(t *testing.T) {
144180 "quote_verified" : true ,
145181 "event_log_verified" : true ,
146182 "report_data" : expectedReportData ,
147- "app_info" : map [string ]string {"compose_hash" : testHash , "app_id" : "app_abc" },
183+ "app_info" : map [string ]string {
184+ "compose_hash" : testHash ,
185+ "app_id" : "app_abc" ,
186+ "key_provider_info" : hex .EncodeToString ([]byte (`{"name":"kms","id":"` + testKMSKey + `"}` )),
187+ },
148188 },
149189 })
150190 }))
@@ -153,7 +193,7 @@ func TestAttestFlow(t *testing.T) {
153193 issuer := & recordingIssuer {token : "secret-token" }
154194 now := time .Unix (100 , 0 ).UTC ()
155195 s := & Server {
156- policy : mustPolicy (t , `{"cluster":"demo","policy_epoch":7,"workloads":[{"workload_id":"demo/worker/0/webdemo","identity":"spiffe://demo/webdemo","consul_service":"webdemo","allowed_compose_hashes":["` + testHash + `"]}]}` ),
196+ policy : mustPolicy (t , `{"cluster":"demo","policy_epoch":7,"kms":{"name":"kms","id":"` + testKMSKey + `"}," workloads":[{"workload_id":"demo/worker/0/webdemo","identity":"spiffe://demo/webdemo","consul_service":"webdemo","allowed_compose_hashes":["`+ testHash + `"]}]}` ),
157197 nonces : NewNonceStore (time .Minute ),
158198 verifier : & VerifierClient {URL : verifier .URL , HTTP : verifier .Client ()},
159199 issuer : issuer ,
@@ -215,6 +255,76 @@ func TestAttestFlow(t *testing.T) {
215255 }
216256}
217257
258+ func TestAttestRejectsKMSMismatch (t * testing.T ) {
259+ var expectedReportData string
260+ verifier := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
261+ writeJSON (w , http .StatusOK , map [string ]any {
262+ "is_valid" : true ,
263+ "details" : map [string ]any {
264+ "quote_verified" : true ,
265+ "event_log_verified" : true ,
266+ "report_data" : expectedReportData ,
267+ "app_info" : map [string ]string {
268+ "compose_hash" : testHash ,
269+ "key_provider_info" : hex .EncodeToString ([]byte (`{"name":"kms","id":"3059301306072a8648ce3d020106082a8648ce3d030107034200040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}` )),
270+ },
271+ },
272+ })
273+ }))
274+ defer verifier .Close ()
275+
276+ s := & Server {
277+ policy : mustPolicy (t , `{"cluster":"demo","policy_epoch":1,"kms":{"name":"kms","id":"` + testKMSKey + `"},"workloads":[{"workload_id":"demo/worker/0/webdemo","identity":"spiffe://demo/webdemo","consul_service":"webdemo","allowed_compose_hashes":["` + testHash + `"]}]}` ),
278+ nonces : NewNonceStore (time .Minute ),
279+ verifier : & VerifierClient {URL : verifier .URL , HTTP : verifier .Client ()},
280+ issuer : & recordingIssuer {token : "secret-token" },
281+ tokenTTL : time .Hour ,
282+ now : func () time.Time { return time .Unix (100 , 0 ).UTC () },
283+ nonceRandom : bytes .NewReader (bytes .Repeat ([]byte {0x55 }, 32 )),
284+ }
285+ ts := httptest .NewServer (s .routes ())
286+ defer ts .Close ()
287+
288+ challengeResp , err := http .Post (ts .URL + "/v1/admission/challenge" , "application/json" , nil )
289+ if err != nil {
290+ t .Fatal (err )
291+ }
292+ var challenge struct {
293+ Nonce string `json:"nonce"`
294+ }
295+ if err := json .NewDecoder (challengeResp .Body ).Decode (& challenge ); err != nil {
296+ t .Fatal (err )
297+ }
298+ _ = challengeResp .Body .Close ()
299+
300+ statement := `{"identity":"spiffe://demo/webdemo","peer_id":"worker-1"}`
301+ expectedReportData , err = reportDataHex (hex .EncodeToString ([]byte (statement )), challenge .Nonce )
302+ if err != nil {
303+ t .Fatal (err )
304+ }
305+ buf , _ := json .Marshal (map [string ]any {
306+ "identity" : "spiffe://demo/webdemo" ,
307+ "binding" : hex .EncodeToString ([]byte (statement )),
308+ "nonce" : challenge .Nonce ,
309+ "attestation" : "aabbcc" ,
310+ })
311+ resp , err := http .Post (ts .URL + "/v1/admission/attest" , "application/json" , bytes .NewReader (buf ))
312+ if err != nil {
313+ t .Fatal (err )
314+ }
315+ defer resp .Body .Close ()
316+ if resp .StatusCode != http .StatusForbidden {
317+ t .Fatalf ("status = %d" , resp .StatusCode )
318+ }
319+ var body map [string ]string
320+ if err := json .NewDecoder (resp .Body ).Decode (& body ); err != nil {
321+ t .Fatal (err )
322+ }
323+ if body ["code" ] != "KMS_POLICY_MISMATCH" {
324+ t .Fatalf ("wrong error body: %+v" , body )
325+ }
326+ }
327+
218328func TestAttestCarriesConsulPermissionsFromPolicy (t * testing.T ) {
219329 var expectedReportData string
220330 verifier := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
0 commit comments