1package cmd 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/url" 7 "os" 8 "path/filepath" 9 "strings" 10 11 "github.com/go-acme/lego/v4/certcrypto" 12 "github.com/urfave/cli" 13) 14 15func createList() cli.Command { 16 return cli.Command{ 17 Name: "list", 18 Usage: "Display certificates and accounts information.", 19 Action: list, 20 Flags: []cli.Flag{ 21 cli.BoolFlag{ 22 Name: "accounts, a", 23 Usage: "Display accounts.", 24 }, 25 cli.BoolFlag{ 26 Name: "names, n", 27 Usage: "Display certificate common names only.", 28 }, 29 }, 30 } 31} 32 33func list(ctx *cli.Context) error { 34 if ctx.Bool("accounts") && !ctx.Bool("names") { 35 if err := listAccount(ctx); err != nil { 36 return err 37 } 38 } 39 40 return listCertificates(ctx) 41} 42 43func listCertificates(ctx *cli.Context) error { 44 certsStorage := NewCertificatesStorage(ctx) 45 46 matches, err := filepath.Glob(filepath.Join(certsStorage.GetRootPath(), "*.crt")) 47 if err != nil { 48 return err 49 } 50 51 names := ctx.Bool("names") 52 53 if len(matches) == 0 { 54 if !names { 55 fmt.Println("No certificates found.") 56 } 57 return nil 58 } 59 60 if !names { 61 fmt.Println("Found the following certs:") 62 } 63 64 for _, filename := range matches { 65 if strings.HasSuffix(filename, ".issuer.crt") { 66 continue 67 } 68 69 data, err := os.ReadFile(filename) 70 if err != nil { 71 return err 72 } 73 74 pCert, err := certcrypto.ParsePEMCertificate(data) 75 if err != nil { 76 return err 77 } 78 79 if names { 80 fmt.Println(pCert.Subject.CommonName) 81 } else { 82 fmt.Println(" Certificate Name:", pCert.Subject.CommonName) 83 fmt.Println(" Domains:", strings.Join(pCert.DNSNames, ", ")) 84 fmt.Println(" Expiry Date:", pCert.NotAfter) 85 fmt.Println(" Certificate Path:", filename) 86 fmt.Println() 87 } 88 } 89 90 return nil 91} 92 93func listAccount(ctx *cli.Context) error { 94 // fake email, needed by NewAccountsStorage 95 if err := ctx.GlobalSet("email", "unknown"); err != nil { 96 return err 97 } 98 99 accountsStorage := NewAccountsStorage(ctx) 100 101 matches, err := filepath.Glob(filepath.Join(accountsStorage.GetRootPath(), "*", "*", "*.json")) 102 if err != nil { 103 return err 104 } 105 106 if len(matches) == 0 { 107 fmt.Println("No accounts found.") 108 return nil 109 } 110 111 fmt.Println("Found the following accounts:") 112 for _, filename := range matches { 113 data, err := os.ReadFile(filename) 114 if err != nil { 115 return err 116 } 117 118 var account Account 119 err = json.Unmarshal(data, &account) 120 if err != nil { 121 return err 122 } 123 124 uri, err := url.Parse(account.Registration.URI) 125 if err != nil { 126 return err 127 } 128 129 fmt.Println(" Email:", account.Email) 130 fmt.Println(" Server:", uri.Host) 131 fmt.Println(" Path:", filepath.Dir(filename)) 132 fmt.Println() 133 } 134 135 return nil 136} 137