From ff7bc131b2b8c2a679662ef0d3ae9de04907754c Mon Sep 17 00:00:00 2001 From: Evan Jarrett Date: Sat, 1 Nov 2025 10:29:11 -0500 Subject: [PATCH] rename example go files for documentation --- examples/plugins/gatekeeper-provider/main.go | 225 ------------------- examples/plugins/ratify-verifier/verifier.go | 214 ------------------ 2 files changed, 439 deletions(-) delete mode 100644 examples/plugins/gatekeeper-provider/main.go delete mode 100644 examples/plugins/ratify-verifier/verifier.go diff --git a/examples/plugins/gatekeeper-provider/main.go b/examples/plugins/gatekeeper-provider/main.go deleted file mode 100644 index e823f85..0000000 --- a/examples/plugins/gatekeeper-provider/main.go +++ /dev/null @@ -1,225 +0,0 @@ -// Package main implements an OPA Gatekeeper External Data Provider for ATProto signature verification. -package main - -import ( - "context" - "encoding/json" - "fmt" - "log" - "net/http" - "os" - "time" -) - -const ( - // DefaultPort is the default HTTP port - DefaultPort = "8080" - - // DefaultTrustPolicyPath is the default trust policy file path - DefaultTrustPolicyPath = "/config/trust-policy.yaml" -) - -// Server is the HTTP server for the external data provider. -type Server struct { - verifier *Verifier - port string - httpServer *http.Server -} - -// ProviderRequest is the request format from Gatekeeper. -type ProviderRequest struct { - Keys []string `json:"keys"` - Values []string `json:"values"` -} - -// ProviderResponse is the response format to Gatekeeper. -type ProviderResponse struct { - SystemError string `json:"system_error,omitempty"` - Responses []map[string]interface{} `json:"responses"` -} - -// VerificationResult holds the result of verifying a single image. -type VerificationResult struct { - Image string `json:"image"` - Verified bool `json:"verified"` - DID string `json:"did,omitempty"` - Handle string `json:"handle,omitempty"` - SignedAt time.Time `json:"signedAt,omitempty"` - CommitCID string `json:"commitCid,omitempty"` - Error string `json:"error,omitempty"` -} - -// NewServer creates a new provider server. -func NewServer(verifier *Verifier, port string) *Server { - return &Server{ - verifier: verifier, - port: port, - } -} - -// Start starts the HTTP server. -func (s *Server) Start() error { - mux := http.NewServeMux() - - // Provider endpoint (called by Gatekeeper) - mux.HandleFunc("/provide", s.handleProvide) - - // Health check endpoints - mux.HandleFunc("/health", s.handleHealth) - mux.HandleFunc("/ready", s.handleReady) - - // Metrics endpoint (Prometheus) - // TODO: Implement metrics - // mux.HandleFunc("/metrics", s.handleMetrics) - - s.httpServer = &http.Server{ - Addr: ":" + s.port, - Handler: mux, - ReadTimeout: 10 * time.Second, - WriteTimeout: 30 * time.Second, - IdleTimeout: 60 * time.Second, - } - - log.Printf("Starting ATProto signature verification provider on port %s", s.port) - return s.httpServer.ListenAndServe() -} - -// Stop gracefully stops the HTTP server. -func (s *Server) Stop(ctx context.Context) error { - if s.httpServer != nil { - return s.httpServer.Shutdown(ctx) - } - return nil -} - -// handleProvide handles the provider endpoint called by Gatekeeper. -func (s *Server) handleProvide(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "method not allowed", http.StatusMethodNotAllowed) - return - } - - // Parse request - var req ProviderRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - log.Printf("ERROR: failed to parse request: %v", err) - http.Error(w, fmt.Sprintf("invalid request: %v", err), http.StatusBadRequest) - return - } - - log.Printf("INFO: received verification request for %d images", len(req.Values)) - - // Verify each image - responses := make([]map[string]interface{}, 0, len(req.Values)) - for _, image := range req.Values { - result := s.verifyImage(r.Context(), image) - responses = append(responses, structToMap(result)) - } - - // Send response - resp := ProviderResponse{ - Responses: responses, - } - - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(resp); err != nil { - log.Printf("ERROR: failed to encode response: %v", err) - } -} - -// verifyImage verifies a single image. -func (s *Server) verifyImage(ctx context.Context, image string) VerificationResult { - start := time.Now() - log.Printf("INFO: verifying image: %s", image) - - // Call verifier - verified, metadata, err := s.verifier.Verify(ctx, image) - duration := time.Since(start) - - if err != nil { - log.Printf("ERROR: verification failed for %s: %v (duration: %v)", image, err, duration) - return VerificationResult{ - Image: image, - Verified: false, - Error: err.Error(), - } - } - - if !verified { - log.Printf("WARN: image %s failed verification (duration: %v)", image, duration) - return VerificationResult{ - Image: image, - Verified: false, - Error: "signature verification failed", - } - } - - log.Printf("INFO: image %s verified successfully (DID: %s, duration: %v)", - image, metadata.DID, duration) - - return VerificationResult{ - Image: image, - Verified: true, - DID: metadata.DID, - Handle: metadata.Handle, - SignedAt: metadata.SignedAt, - CommitCID: metadata.CommitCID, - } -} - -// handleHealth handles health check requests. -func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{ - "status": "ok", - "version": "1.0.0", - }) -} - -// handleReady handles readiness check requests. -func (s *Server) handleReady(w http.ResponseWriter, r *http.Request) { - // TODO: Check dependencies (DID resolver, PDS connectivity) - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{ - "status": "ready", - }) -} - -// structToMap converts a struct to a map for JSON encoding. -func structToMap(v interface{}) map[string]interface{} { - data, _ := json.Marshal(v) - var m map[string]interface{} - json.Unmarshal(data, &m) - return m -} - -func main() { - // Load configuration - port := os.Getenv("HTTP_PORT") - if port == "" { - port = DefaultPort - } - - trustPolicyPath := os.Getenv("TRUST_POLICY_PATH") - if trustPolicyPath == "" { - trustPolicyPath = DefaultTrustPolicyPath - } - - // Create verifier - verifier, err := NewVerifier(trustPolicyPath) - if err != nil { - log.Fatalf("FATAL: failed to create verifier: %v", err) - } - - // Create server - server := NewServer(verifier, port) - - // Start server - if err := server.Start(); err != nil && err != http.ErrServerClosed { - log.Fatalf("FATAL: server error: %v", err) - } -} - -// TODO: Implement verifier.go with ATProto signature verification logic -// TODO: Implement resolver.go with DID resolution -// TODO: Implement crypto.go with K-256 signature verification diff --git a/examples/plugins/ratify-verifier/verifier.go b/examples/plugins/ratify-verifier/verifier.go deleted file mode 100644 index 732d0f3..0000000 --- a/examples/plugins/ratify-verifier/verifier.go +++ /dev/null @@ -1,214 +0,0 @@ -// Package atproto implements a Ratify verifier plugin for ATProto signatures. -package atproto - -import ( - "context" - "encoding/json" - "fmt" - "time" - - "github.com/ratify-project/ratify/pkg/common" - "github.com/ratify-project/ratify/pkg/ocispecs" - "github.com/ratify-project/ratify/pkg/referrerstore" - "github.com/ratify-project/ratify/pkg/verifier" -) - -const ( - // VerifierName is the name of this verifier - VerifierName = "atproto" - - // VerifierType is the type of this verifier - VerifierType = "atproto" - - // ATProtoSignatureArtifactType is the OCI artifact type for ATProto signatures - ATProtoSignatureArtifactType = "application/vnd.atproto.signature.v1+json" -) - -// ATProtoVerifier implements the Ratify ReferenceVerifier interface for ATProto signatures. -type ATProtoVerifier struct { - name string - config ATProtoConfig - resolver *Resolver - verifier *SignatureVerifier - trustStore *TrustStore -} - -// ATProtoConfig holds configuration for the ATProto verifier. -type ATProtoConfig struct { - // TrustPolicyPath is the path to the trust policy YAML file - TrustPolicyPath string `json:"trustPolicyPath"` - - // DIDResolverTimeout is the timeout for DID resolution - DIDResolverTimeout time.Duration `json:"didResolverTimeout"` - - // PDSTimeout is the timeout for PDS XRPC calls - PDSTimeout time.Duration `json:"pdsTimeout"` - - // CacheEnabled enables caching of DID documents and public keys - CacheEnabled bool `json:"cacheEnabled"` - - // CacheTTL is the cache TTL for DID documents and public keys - CacheTTL time.Duration `json:"cacheTTL"` -} - -// ATProtoSignature represents the ATProto signature metadata stored in the OCI artifact. -type ATProtoSignature struct { - Type string `json:"$type"` - Version string `json:"version"` - Subject struct { - Digest string `json:"digest"` - MediaType string `json:"mediaType"` - } `json:"subject"` - ATProto struct { - DID string `json:"did"` - Handle string `json:"handle"` - PDSEndpoint string `json:"pdsEndpoint"` - RecordURI string `json:"recordUri"` - CommitCID string `json:"commitCid"` - SignedAt time.Time `json:"signedAt"` - } `json:"atproto"` - Signature struct { - Algorithm string `json:"algorithm"` - KeyID string `json:"keyId"` - PublicKeyMultibase string `json:"publicKeyMultibase"` - } `json:"signature"` -} - -// NewATProtoVerifier creates a new ATProto verifier instance. -func NewATProtoVerifier(name string, config ATProtoConfig) (*ATProtoVerifier, error) { - // Load trust policy - trustStore, err := LoadTrustStore(config.TrustPolicyPath) - if err != nil { - return nil, fmt.Errorf("failed to load trust policy: %w", err) - } - - // Create resolver with caching - resolver := NewResolver(config.DIDResolverTimeout, config.CacheEnabled, config.CacheTTL) - - // Create signature verifier - verifier := NewSignatureVerifier(config.PDSTimeout) - - return &ATProtoVerifier{ - name: name, - config: config, - resolver: resolver, - verifier: verifier, - trustStore: trustStore, - }, nil -} - -// Name returns the name of this verifier. -func (v *ATProtoVerifier) Name() string { - return v.name -} - -// Type returns the type of this verifier. -func (v *ATProtoVerifier) Type() string { - return VerifierType -} - -// CanVerify returns true if this verifier can verify the given artifact type. -func (v *ATProtoVerifier) CanVerify(artifactType string) bool { - return artifactType == ATProtoSignatureArtifactType -} - -// VerifyReference verifies an ATProto signature artifact. -func (v *ATProtoVerifier) VerifyReference( - ctx context.Context, - subjectRef common.Reference, - referenceDesc ocispecs.ReferenceDescriptor, - store referrerstore.ReferrerStore, -) (verifier.VerifierResult, error) { - // 1. Fetch signature blob from store - sigBlob, err := store.GetBlobContent(ctx, subjectRef, referenceDesc.Digest) - if err != nil { - return v.failureResult(fmt.Sprintf("failed to fetch signature blob: %v", err)), err - } - - // 2. Parse ATProto signature metadata - var sigData ATProtoSignature - if err := json.Unmarshal(sigBlob, &sigData); err != nil { - return v.failureResult(fmt.Sprintf("failed to parse signature metadata: %v", err)), err - } - - // Validate signature format - if err := v.validateSignature(&sigData); err != nil { - return v.failureResult(fmt.Sprintf("invalid signature format: %v", err)), err - } - - // 3. Check trust policy first (fail fast if DID not trusted) - if !v.trustStore.IsTrusted(sigData.ATProto.DID, time.Now()) { - return v.failureResult(fmt.Sprintf("DID %s not in trusted list", sigData.ATProto.DID)), - fmt.Errorf("untrusted DID") - } - - // 4. Resolve DID to public key - pubKey, err := v.resolver.ResolveDIDToPublicKey(ctx, sigData.ATProto.DID) - if err != nil { - return v.failureResult(fmt.Sprintf("failed to resolve DID: %v", err)), err - } - - // 5. Fetch repository commit from PDS - commit, err := v.verifier.FetchCommit(ctx, sigData.ATProto.PDSEndpoint, - sigData.ATProto.DID, sigData.ATProto.CommitCID) - if err != nil { - return v.failureResult(fmt.Sprintf("failed to fetch commit: %v", err)), err - } - - // 6. Verify K-256 signature - if err := v.verifier.VerifySignature(pubKey, commit); err != nil { - return v.failureResult(fmt.Sprintf("signature verification failed: %v", err)), err - } - - // 7. Success - return detailed result - return verifier.VerifierResult{ - IsSuccess: true, - Name: v.name, - Type: v.Type(), - Message: fmt.Sprintf("Successfully verified ATProto signature for DID %s", sigData.ATProto.DID), - Extensions: map[string]interface{}{ - "did": sigData.ATProto.DID, - "handle": sigData.ATProto.Handle, - "signedAt": sigData.ATProto.SignedAt, - "commitCid": sigData.ATProto.CommitCID, - "pdsEndpoint": sigData.ATProto.PDSEndpoint, - }, - }, nil -} - -// validateSignature validates the signature metadata format. -func (v *ATProtoVerifier) validateSignature(sig *ATProtoSignature) error { - if sig.Type != "io.atcr.atproto.signature" { - return fmt.Errorf("invalid signature type: %s", sig.Type) - } - if sig.ATProto.DID == "" { - return fmt.Errorf("missing DID") - } - if sig.ATProto.PDSEndpoint == "" { - return fmt.Errorf("missing PDS endpoint") - } - if sig.ATProto.CommitCID == "" { - return fmt.Errorf("missing commit CID") - } - if sig.Signature.Algorithm != "ECDSA-K256-SHA256" { - return fmt.Errorf("unsupported signature algorithm: %s", sig.Signature.Algorithm) - } - return nil -} - -// failureResult creates a failure result with the given message. -func (v *ATProtoVerifier) failureResult(message string) verifier.VerifierResult { - return verifier.VerifierResult{ - IsSuccess: false, - Name: v.name, - Type: v.Type(), - Message: message, - Extensions: map[string]interface{}{ - "error": message, - }, - } -} - -// TODO: Implement resolver.go with DID resolution logic -// TODO: Implement crypto.go with K-256 signature verification -// TODO: Implement config.go with trust policy loading