-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.go
146 lines (121 loc) · 3.02 KB
/
app.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package app
import (
"flag"
"fmt"
"os"
"github.com/canstand/ctlcheck/ctl"
"github.com/carlmjohnson/flagext"
"github.com/pterm/pterm"
"gopkg.in/yaml.v3"
)
const AppName = "ctlcheck"
func CLI(args []string) error {
var app appEnv
err := app.ParseArgs(args)
if err != nil {
return err
}
if err = app.Exec(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
}
return err
}
func (app *appEnv) ParseArgs(args []string) error {
fl := flag.NewFlagSet(AppName, flag.ContinueOnError)
app.AppleCTL = ctl.NewAppleCTL()
app.MicrosoftCTL = ctl.NewMicrosoftCTL()
app.MozillaCTL = ctl.NewMozillaCTL()
app.Allow = ctl.Entrys{}
var (
offline bool
save bool
raw bool
)
fl.BoolVar(&offline, "offline", false, "load data from ctlcheck.yml instead of fetch from CCADB")
fl.BoolVar(&save, "save", false, "save data to ctlcheck.yml")
fl.BoolVar(&raw, "raw", false, "print unstyled raw output (set it if output is written to a file)")
fl.Usage = func() {
fmt.Fprintf(fl.Output(), `ctlcheck - %s
A utility to check the certificate trust list (CTL)
Usage:
ctlcheck [options]
Options:
`, getAppVersion())
fl.PrintDefaults()
}
if err := fl.Parse(args); err != nil {
return err
}
if err := flagext.ParseEnv(fl, AppName); err != nil {
return err
}
app.offline = offline
app.save = save
if raw {
pterm.DisableStyling()
}
return nil
}
type appEnv struct {
AppleCTL *ctl.AppleCTL `yaml:"apple_ctl,omitempty"`
MicrosoftCTL *ctl.MicrosoftCTL `yaml:"micrsoft_ctl,omitempty"`
MozillaCTL *ctl.MozillaCTL `yaml:"mozilla_ctl,omitempty"`
Allow ctl.Entrys `yaml:"allow,omitempty"`
offline bool `yaml:"-"`
save bool `yaml:"-"`
}
func (app *appEnv) Exec() (err error) {
spinnerLoading, _ := pterm.DefaultSpinner.Start("Load CTL...")
if app.offline {
spinnerLoading.UpdateText("Load CTL...from file")
err = app.Load("ctlcheck.yml")
if err != nil {
spinnerLoading.Fail(err)
return err
}
} else {
_ = app.Load("ctlcheck.yml") // load allow items if file exist
spinnerLoading.UpdateText("Fetch CTL...")
err = app.fetchCtl()
if err != nil {
spinnerLoading.Fail(err)
return err
}
if app.save {
spinnerLoading.UpdateText("Fetch CTL..., save to file")
err = app.Save("ctlcheck.yml")
if err != nil {
spinnerLoading.Fail(err)
return err
}
}
}
spinnerLoading.Success()
roots, err := ctl.LoadSystemRoots()
if err != nil {
pterm.PrintOnErrorf("load system root CAs failed: %v", err)
return err
}
results := app.verify(roots.Certs, app.Allow)
pterm.DefaultSection.WithLevel(2).Print("System Root CA")
pterm.Print(results.ConsoleReport())
return err
}
// Save as yaml file
func (app *appEnv) Save(file string) error {
data, err := yaml.Marshal(app)
if err != nil {
return err
}
err = os.WriteFile(file, data, 0o644)
return err
}
// Load from yaml file
func (app *appEnv) Load(file string) error {
data, err := os.ReadFile(file)
if err != nil {
return err
}
err = yaml.Unmarshal(data, app)
return err
}