...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cmd
16
17 import (
18 "context"
19 "encoding/pem"
20 "fmt"
21 "os"
22
23 ct "github.com/google/certificate-transparency-go"
24 "github.com/google/certificate-transparency-go/x509"
25 "github.com/google/certificate-transparency-go/x509util"
26 "github.com/spf13/cobra"
27 "k8s.io/klog/v2"
28 )
29
30 var (
31 getFirst int64
32 getLast int64
33 chainOut bool
34 textOut bool
35 )
36
37 func init() {
38 cmd := cobra.Command{
39 Use: fmt.Sprintf("get-entries %s --first=idx [--last=idx]", connectionFlags),
40 Aliases: []string{"getentries", "entries"},
41 Short: "Fetch a range of entries in the log",
42 Args: cobra.MaximumNArgs(0),
43 Run: func(cmd *cobra.Command, _ []string) {
44 runGetEntries(cmd.Context())
45 },
46 }
47 cmd.Flags().Int64Var(&getFirst, "first", -1, "First entry to get")
48 cmd.Flags().Int64Var(&getLast, "last", -1, "Last entry to get")
49 cmd.Flags().BoolVar(&chainOut, "chain", false, "Display entire certificate chain")
50 cmd.Flags().BoolVar(&textOut, "text", true, "Display certificates as text")
51 rootCmd.AddCommand(&cmd)
52 }
53
54
55 func runGetEntries(ctx context.Context) {
56 logClient := connect(ctx)
57 if getFirst == -1 {
58 klog.Exit("No -first option supplied")
59 }
60 if getLast == -1 {
61 getLast = getFirst
62 }
63 rsp, err := logClient.GetRawEntries(ctx, getFirst, getLast)
64 if err != nil {
65 exitWithDetails(err)
66 }
67
68 for i, rawEntry := range rsp.Entries {
69 index := getFirst + int64(i)
70 rle, err := ct.RawLogEntryFromLeaf(index, &rawEntry)
71 if err != nil {
72 fmt.Printf("Index=%d Failed to unmarshal leaf entry: %v", index, err)
73 continue
74 }
75 showRawLogEntry(rle)
76 }
77 }
78
79 func showRawLogEntry(rle *ct.RawLogEntry) {
80 ts := rle.Leaf.TimestampedEntry
81 when := ct.TimestampToTime(ts.Timestamp)
82 fmt.Printf("Index=%d Timestamp=%d (%v) ", rle.Index, ts.Timestamp, when)
83
84 switch ts.EntryType {
85 case ct.X509LogEntryType:
86 fmt.Printf("X.509 certificate:\n")
87 showRawCert(*ts.X509Entry)
88 case ct.PrecertLogEntryType:
89 fmt.Printf("pre-certificate from issuer with keyhash %x:\n", ts.PrecertEntry.IssuerKeyHash)
90 showRawCert(rle.Cert)
91 default:
92 fmt.Printf("Unhandled log entry type %d\n", ts.EntryType)
93 }
94 if chainOut {
95 for _, c := range rle.Chain {
96 showRawCert(c)
97 }
98 }
99 }
100
101 func showRawCert(cert ct.ASN1Cert) {
102 if textOut {
103 c, err := x509.ParseCertificate(cert.Data)
104 if err != nil {
105 klog.Errorf("Error parsing certificate: %q", err.Error())
106 }
107 if c == nil {
108 return
109 }
110 showParsedCert(c)
111 } else {
112 showPEMData(cert.Data)
113 }
114 }
115
116 func showParsedCert(cert *x509.Certificate) {
117 if textOut {
118 fmt.Printf("%s\n", x509util.CertificateToString(cert))
119 } else {
120 showPEMData(cert.Raw)
121 }
122 }
123
124 func showPEMData(data []byte) {
125 if err := pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: data}); err != nil {
126 klog.Errorf("Failed to PEM encode cert: %q", err.Error())
127 }
128 }
129
View as plain text