Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 1 | package model |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "fmt" |
| 6 | "net" |
| 7 | "strings" |
| 8 | "time" |
| 9 | |
| 10 | pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto" |
| 11 | "code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model/migrations" |
| 12 | migrate "github.com/golang-migrate/migrate/v4" |
| 13 | _ "github.com/golang-migrate/migrate/v4/database/cockroachdb" |
| 14 | "github.com/jmoiron/sqlx" |
| 15 | _ "github.com/lib/pq" |
| 16 | ) |
| 17 | |
| 18 | type Model interface { |
| 19 | MigrateUp() error |
| 20 | |
| 21 | RecordPeeringDBPeers(ctx context.Context, members []*pb.PeeringDBMember) error |
| 22 | RecordPeeringDBPeerRouters(ctx context.Context, members []*pb.PeeringDBMember) error |
| 23 | GetPeeringDBPeer(ctx context.Context, asn int64) (*pb.PeeringDBMember, error) |
| 24 | |
| 25 | GetCheckablePeers(ctx context.Context) ([]*Peer, error) |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 26 | SubmitPeerCheckResults(ctx context.Context, checkName string, res []*PeerCheckResult) error |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 27 | GetPeerCheckResults(ctx context.Context, asn []int64) ([]*PeerCheckResult, error) |
| 28 | |
| 29 | UpdatePGPKey(ctx context.Context, key *PeerPGPKey) error |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 30 | GetPGPKeysRequiringAttention(ctx context.Context) ([]*PeerPGPKey, error) |
| 31 | ValidatePGPKeys(ctx context.Context, positive, negative []string) error |
| 32 | GetPeerPGPKey(ctx context.Context, asn int64) (*PeerPGPKey, error) |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 33 | |
| 34 | ConfigureMissingSessions(ctx context.Context, gen func() SessionConfig) error |
| 35 | |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 36 | GetPeerConfiguration(ctx context.Context) ([]*PeerConfiguration, error) |
| 37 | |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 38 | UpdateAllowedPrefixes(ctx context.Context, asn int64, prefixes []*AllowedPrefix) error |
| 39 | GetAllowedPrefixes(ctx context.Context, asn int64) ([]*AllowedPrefix, error) |
| 40 | } |
| 41 | |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 42 | type Router struct { |
| 43 | V6 net.IP |
| 44 | V4 net.IP |
| 45 | Config *SessionConfig |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 46 | } |
| 47 | |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 48 | func (p *Router) String() string { |
| 49 | if p == nil { |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 50 | return "<nil>" |
| 51 | } |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 52 | return fmt.Sprintf("%+v", *p) |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | type Peer struct { |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 56 | ASN int64 |
| 57 | Name string |
| 58 | Routers []*Router |
| 59 | } |
| 60 | |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 61 | func (p *Peer) String() string { |
| 62 | if p == nil { |
| 63 | return "<nil>" |
| 64 | } |
| 65 | return fmt.Sprintf("%+v", *p) |
| 66 | } |
| 67 | |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 68 | type PeerCheckStatus int |
| 69 | |
| 70 | const ( |
| 71 | PeerCheckStatus_Invalid PeerCheckStatus = iota |
| 72 | PeerCheckStatus_Okay |
| 73 | PeerCheckStatus_Failed |
| 74 | PeerCheckStatus_SoftFailed |
| 75 | ) |
| 76 | |
| 77 | type PeerCheckResult struct { |
| 78 | PeerASN int64 |
| 79 | CheckName string |
| 80 | Time time.Time |
| 81 | Status PeerCheckStatus |
| 82 | Message string |
| 83 | } |
| 84 | |
| 85 | func (p *PeerCheckResult) String() string { |
| 86 | if p == nil { |
| 87 | return "<nil>" |
| 88 | } |
| 89 | return fmt.Sprintf("%+v", *p) |
| 90 | } |
| 91 | |
| 92 | type PeerPGPKey struct { |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 93 | PeerASN int64 |
| 94 | Fingerprint string |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 95 | State string |
| 96 | } |
| 97 | |
| 98 | func (p *PeerPGPKey) String() string { |
| 99 | if p == nil { |
| 100 | return "<nil>" |
| 101 | } |
| 102 | return fmt.Sprintf("%+v", *p) |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | type SessionConfig struct { |
| 106 | BGPSecret string |
| 107 | } |
| 108 | |
Serge Bazanski | ec71cb5 | 2019-08-22 18:13:13 +0200 | [diff] [blame] | 109 | func (p *SessionConfig) String() string { |
| 110 | if p == nil { |
| 111 | return "<nil>" |
| 112 | } |
| 113 | return fmt.Sprintf("%+v", *p) |
| 114 | } |
| 115 | |
| 116 | type PeerConfiguration struct { |
| 117 | Peer Peer |
| 118 | Key PeerPGPKey |
| 119 | } |
| 120 | |
| 121 | func (p *PeerConfiguration) String() string { |
| 122 | if p == nil { |
| 123 | return "<nil>" |
| 124 | } |
| 125 | return fmt.Sprintf("%+v", *p) |
| 126 | } |
| 127 | |
Sergiusz Bazanski | 1fad2e5 | 2019-08-01 20:16:27 +0200 | [diff] [blame] | 128 | type AllowedPrefix struct { |
| 129 | Prefix net.IPNet |
| 130 | MaxLength int64 |
| 131 | TA string |
| 132 | } |
| 133 | |
| 134 | func (p *AllowedPrefix) String() string { |
| 135 | if p == nil { |
| 136 | return "<nil>" |
| 137 | } |
| 138 | return fmt.Sprintf("%+v", *p) |
| 139 | } |
| 140 | |
| 141 | type sqlModel struct { |
| 142 | db *sqlx.DB |
| 143 | dsn string |
| 144 | } |
| 145 | |
| 146 | func Connect(ctx context.Context, driver, dsn string) (Model, error) { |
| 147 | if dsn == "" { |
| 148 | return nil, fmt.Errorf("dsn cannot be empty") |
| 149 | } |
| 150 | |
| 151 | db, err := sqlx.ConnectContext(ctx, driver, dsn) |
| 152 | if err != nil { |
| 153 | return nil, fmt.Errorf("could not connect to database: %v", err) |
| 154 | } |
| 155 | |
| 156 | return &sqlModel{ |
| 157 | db: db, |
| 158 | dsn: dsn, |
| 159 | }, nil |
| 160 | } |
| 161 | |
| 162 | func (m *sqlModel) MigrateUp() error { |
| 163 | dsn := "cockroach://" + strings.TrimPrefix(m.dsn, "postgres://") |
| 164 | mig, err := migrations.New(dsn) |
| 165 | if err != nil { |
| 166 | return err |
| 167 | } |
| 168 | err = mig.Up() |
| 169 | switch err { |
| 170 | case migrate.ErrNoChange: |
| 171 | return nil |
| 172 | default: |
| 173 | return err |
| 174 | } |
| 175 | } |