github.com/google/osv-scalibr@v0.4.1/enricher/hcpidentity/hcpidentity_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package hcpidentity 16 17 import ( 18 "context" 19 "net/http" 20 "net/http/httptest" 21 "testing" 22 23 "github.com/google/osv-scalibr/enricher" 24 "github.com/google/osv-scalibr/inventory" 25 "github.com/google/osv-scalibr/veles/secrets/hcp" 26 ) 27 28 func TestEnrich_PopulatesServicePrincipal(t *testing.T) { 29 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 if r.Method != http.MethodGet || r.URL.Path != "/iam/2019-12-10/caller-identity" { 31 http.Error(w, "not found", http.StatusNotFound) 32 return 33 } 34 w.Header().Set("Content-Type", "application/json") 35 w.WriteHeader(http.StatusOK) 36 _, _ = w.Write([]byte(`{ 37 "principal": { 38 "id": "svc-abc@proj-123", 39 "type": "PRINCIPAL_TYPE_SERVICE", 40 "service": { 41 "id": "svc-abc@proj-123", 42 "name": "svc-abc", 43 "organization_id": "org-001", 44 "project_id": "proj-123" 45 }, 46 "group_ids": ["g1","g2"] 47 } 48 }`)) 49 })) 50 defer srv.Close() 51 52 e := NewWithBaseURL(srv.URL) 53 inv := &inventory.Inventory{Secrets: []*inventory.Secret{{Secret: hcp.AccessToken{Token: "t"}}}} 54 if err := e.Enrich(context.Background(), &enricher.ScanInput{}, inv); err != nil { 55 t.Fatalf("Enrich error: %v", err) 56 } 57 tok, ok := inv.Secrets[0].Secret.(hcp.AccessToken) 58 if !ok { 59 t.Fatalf("unexpected type: %T", inv.Secrets[0].Secret) 60 } 61 if tok.OrganizationID != "org-001" || tok.ProjectID != "proj-123" || tok.PrincipalID != "svc-abc@proj-123" || tok.ServiceName != "svc-abc" || tok.PrincipalType != "PRINCIPAL_TYPE_SERVICE" { 62 t.Errorf("unexpected identity: %+v", tok) 63 } 64 if tok.UserEmail != "" || tok.UserID != "" { 65 t.Errorf("unexpected user email or user id: %+v", tok) 66 } 67 if len(tok.GroupIDs) != 2 || tok.GroupIDs[0] != "g1" || tok.GroupIDs[1] != "g2" { 68 t.Errorf("unexpected group ids: %+v", tok.GroupIDs) 69 } 70 } 71 72 func TestEnrich_SkipsOnNon200(t *testing.T) { 73 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 74 w.WriteHeader(http.StatusUnauthorized) 75 })) 76 defer srv.Close() 77 78 e := NewWithBaseURL(srv.URL) 79 inv := &inventory.Inventory{Secrets: []*inventory.Secret{{Secret: hcp.AccessToken{Token: "t"}}}} 80 if err := e.Enrich(context.Background(), &enricher.ScanInput{}, inv); err != nil { 81 t.Fatalf("Enrich error: %v", err) 82 } 83 tok := inv.Secrets[0].Secret.(hcp.AccessToken) 84 if tok.OrganizationID != "" || tok.ProjectID != "" || tok.PrincipalID != "" || tok.ServiceName != "" || tok.PrincipalType != "" || len(tok.GroupIDs) != 0 { 85 t.Errorf("should not enrich on non-200: %+v", tok) 86 } 87 } 88 89 func TestEnrich_ConnectionError(t *testing.T) { 90 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) 91 base := srv.URL 92 srv.Close() 93 94 e := NewWithBaseURL(base) 95 inv := &inventory.Inventory{Secrets: []*inventory.Secret{{Secret: hcp.AccessToken{Token: "t"}}}} 96 if err := e.Enrich(context.Background(), &enricher.ScanInput{}, inv); err != nil { 97 t.Fatalf("Enrich error: %v", err) 98 } 99 tok := inv.Secrets[0].Secret.(hcp.AccessToken) 100 if tok.OrganizationID != "" { 101 t.Errorf("unexpected enrichment on connection error: %+v", tok) 102 } 103 } 104 105 func TestEnrich_SkipsNonHCPSecret(t *testing.T) { 106 e := New() 107 inv := &inventory.Inventory{Secrets: []*inventory.Secret{{Secret: struct{ X string }{X: "noop"}}}} 108 if err := e.Enrich(context.Background(), &enricher.ScanInput{}, inv); err != nil { 109 t.Fatalf("Enrich error: %v", err) 110 } 111 } 112 113 func TestEnrich_ContextCanceled(t *testing.T) { 114 e := New() 115 inv := &inventory.Inventory{Secrets: []*inventory.Secret{{Secret: hcp.AccessToken{Token: "t"}}}} 116 ctx, cancel := context.WithCancel(context.Background()) 117 cancel() 118 if err := e.Enrich(ctx, &enricher.ScanInput{}, inv); err == nil { 119 t.Fatalf("expected context error, got nil") 120 } 121 }