go.ligato.io/vpp-agent/v3@v3.5.0/plugins/restapi/plugin_restapi.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package restapi 16 17 import ( 18 "fmt" 19 "net/http" 20 "sync" 21 22 "go.ligato.io/cn-infra/v2/infra" 23 "go.ligato.io/cn-infra/v2/rpc/rest" 24 access "go.ligato.io/cn-infra/v2/rpc/rest/security/model/access-security" 25 "go.ligato.io/cn-infra/v2/servicelabel" 26 "go.ligato.io/vpp-agent/v3/plugins/govppmux" 27 vpevppcalls "go.ligato.io/vpp-agent/v3/plugins/govppmux/vppcalls" 28 kvscheduler "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 29 linuxifplugin "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin" 30 iflinuxcalls "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/linuxcalls" 31 l3linuxcalls "go.ligato.io/vpp-agent/v3/plugins/linux/l3plugin/linuxcalls" 32 "go.ligato.io/vpp-agent/v3/plugins/linux/nsplugin" 33 "go.ligato.io/vpp-agent/v3/plugins/netalloc" 34 "go.ligato.io/vpp-agent/v3/plugins/orchestrator" 35 "go.ligato.io/vpp-agent/v3/plugins/restapi/resturl" 36 telemetryvppcalls "go.ligato.io/vpp-agent/v3/plugins/telemetry/vppcalls" 37 abfvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/vppcalls" 38 "go.ligato.io/vpp-agent/v3/plugins/vpp/aclplugin" 39 aclvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/aclplugin/vppcalls" 40 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin" 41 ifvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" 42 ipsecvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/vppcalls" 43 "go.ligato.io/vpp-agent/v3/plugins/vpp/l2plugin" 44 l2vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/l2plugin/vppcalls" 45 "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin" 46 l3vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" 47 natvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/natplugin/vppcalls" 48 puntvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls" 49 wireguardvppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/wireguardplugin/vppcalls" 50 ) 51 52 // REST api methods 53 const ( 54 GET = http.MethodGet 55 POST = http.MethodPost 56 PUT = http.MethodPut 57 ) 58 59 // Default Go routine count used to retrieve linux configuration 60 const defaultGoRoutineCount = 10 61 62 // Plugin registers Rest Plugin 63 type Plugin struct { 64 Deps 65 66 // Index page 67 index *index 68 69 // Handlers 70 vpeHandler vpevppcalls.VppCoreAPI 71 teleHandler telemetryvppcalls.TelemetryVppAPI 72 // VPP Handlers 73 abfHandler abfvppcalls.ABFVppRead 74 aclHandler aclvppcalls.ACLVppRead 75 ifHandler ifvppcalls.InterfaceVppRead 76 natHandler natvppcalls.NatVppRead 77 l2Handler l2vppcalls.L2VppAPI 78 l3Handler l3vppcalls.L3VppAPI 79 ipSecHandler ipsecvppcalls.IPSecVPPRead 80 puntHandler puntvppcalls.PuntVPPRead 81 wireguardHandler wireguardvppcalls.WgVppRead 82 // Linux handlers 83 linuxIfHandler iflinuxcalls.NetlinkAPIRead 84 linuxL3Handler l3linuxcalls.NetlinkAPIRead 85 86 govppmux sync.Mutex 87 } 88 89 // Deps represents dependencies of Rest Plugin 90 type Deps struct { 91 infra.PluginDeps 92 HTTPHandlers rest.HTTPHandlers 93 VPP govppmux.API 94 ServiceLabel servicelabel.ReaderAPI 95 AddrAlloc netalloc.AddressAllocator 96 VPPACLPlugin aclplugin.API 97 VPPIfPlugin ifplugin.API 98 VPPL2Plugin *l2plugin.L2Plugin 99 VPPL3Plugin *l3plugin.L3Plugin 100 LinuxIfPlugin linuxifplugin.API 101 NsPlugin nsplugin.API 102 Dispatcher orchestrator.Dispatcher 103 KVScheduler kvscheduler.KVScheduler 104 } 105 106 // index defines map of main index page entries 107 type index struct { 108 ItemMap map[string][]indexItem 109 } 110 111 // indexItem is single index page entry 112 type indexItem struct { 113 Name string 114 Path string 115 } 116 117 // Init initializes the Rest Plugin 118 func (p *Plugin) Init() (err error) { 119 // VPP Indexes 120 ifIndexes := p.VPPIfPlugin.GetInterfaceIndex() 121 bdIndexes := p.VPPL2Plugin.GetBDIndex() 122 dhcpIndexes := p.VPPIfPlugin.GetDHCPIndex() 123 aclIndexes := p.VPPACLPlugin.GetACLIndex() // TODO: make ACL optional 124 vrfIndexes := p.VPPL3Plugin.GetVRFIndex() 125 126 // Linux Indexes 127 linuxIfIndexes := p.LinuxIfPlugin.GetInterfaceIndex() 128 129 // Initialize VPP handlers 130 p.vpeHandler, err = vpevppcalls.NewHandler(p.VPP) 131 if err != nil { 132 return fmt.Errorf("VPP core handler error: %w", err) 133 } else if p.vpeHandler == nil { 134 p.Log.Info("VPP core handler is not available, it will be skipped") 135 } 136 p.teleHandler = telemetryvppcalls.CompatibleTelemetryHandler(p.VPP) 137 if p.teleHandler == nil { 138 p.Log.Info("VPP Telemetry handler is not available, it will be skipped") 139 } 140 141 // core 142 p.ifHandler = ifvppcalls.CompatibleInterfaceVppHandler(p.VPP, p.Log) 143 if p.ifHandler == nil { 144 p.Log.Info("VPP Interface handler is not available, it will be skipped") 145 } 146 p.l2Handler = l2vppcalls.CompatibleL2VppHandler(p.VPP, ifIndexes, bdIndexes, p.Log) 147 if p.l2Handler == nil { 148 p.Log.Info("VPP L2 handler is not available, it will be skipped") 149 } 150 p.l3Handler = l3vppcalls.CompatibleL3VppHandler(p.VPP, ifIndexes, vrfIndexes, p.AddrAlloc, p.Log) 151 if p.l3Handler == nil { 152 p.Log.Info("VPP L3 handler is not available, it will be skipped") 153 } 154 p.ipSecHandler = ipsecvppcalls.CompatibleIPSecVppHandler(p.VPP, ifIndexes, p.Log) 155 if p.ipSecHandler == nil { 156 p.Log.Info("VPP IPSec handler is not available, it will be skipped") 157 } 158 159 // plugins (might not be available - disabled) 160 p.abfHandler = abfvppcalls.CompatibleABFHandler(p.VPP, aclIndexes, ifIndexes, p.Log) 161 if p.abfHandler == nil { 162 p.Log.Infof("ABF handler is not available, it will be skipped") 163 } 164 p.aclHandler = aclvppcalls.CompatibleACLHandler(p.VPP, ifIndexes) 165 if p.aclHandler == nil { 166 p.Log.Infof("ACL handler is not available, it will be skipped") 167 } 168 p.natHandler = natvppcalls.CompatibleNatVppHandler(p.VPP, ifIndexes, dhcpIndexes, p.Log) 169 if p.natHandler == nil { 170 p.Log.Infof("NAT handler is not available, it will be skipped") 171 } 172 p.puntHandler = puntvppcalls.CompatiblePuntVppHandler(p.VPP, ifIndexes, p.Log) 173 if p.puntHandler == nil { 174 p.Log.Infof("Punt handler is not available, it will be skipped") 175 } 176 p.wireguardHandler = wireguardvppcalls.CompatibleWgVppHandler(p.VPP, ifIndexes, p.Log) 177 if p.wireguardHandler == nil { 178 p.Log.Info("Wireguard handler is not available, it will be skipped") 179 } 180 181 // Linux handlers 182 p.linuxIfHandler = iflinuxcalls.NewNetLinkHandler(p.NsPlugin, linuxIfIndexes, p.ServiceLabel.GetAgentPrefix(), 183 defaultGoRoutineCount, p.Log) 184 p.linuxL3Handler = l3linuxcalls.NewNetLinkHandler(p.NsPlugin, linuxIfIndexes, defaultGoRoutineCount, p.Log) 185 186 p.index = &index{ 187 ItemMap: getIndexPageItems(), 188 } 189 190 // Register permission groups, used if REST security is enabled 191 p.HTTPHandlers.RegisterPermissionGroup(getPermissionsGroups()...) 192 193 return nil 194 } 195 196 // AfterInit is used to register HTTP handlers 197 func (p *Plugin) AfterInit() (err error) { 198 // Info handlers. 199 p.registerInfoHandlers() 200 // NB configuration handlers. 201 p.registerNBConfigurationHandlers() 202 // VPP handlers 203 p.registerTelemetryHandlers() 204 // core 205 p.registerInterfaceHandlers() 206 p.registerL2Handlers() 207 p.registerL3Handlers() 208 p.registerIPSecHandlers() 209 // plugins 210 p.registerABFHandler() 211 p.registerACLHandlers() 212 p.registerNATHandlers() 213 p.registerPuntHandlers() 214 // Linux handlers 215 p.registerLinuxInterfaceHandlers() 216 p.registerLinuxL3Handlers() 217 // Index and stats handlers 218 p.registerIndexHandlers() 219 p.registerStatsHandler() 220 return nil 221 } 222 223 // Close is used to clean up resources used by Plugin 224 func (p *Plugin) Close() error { 225 return nil 226 } 227 228 // Fill index item lists 229 func getIndexPageItems() map[string][]indexItem { 230 idxMap := map[string][]indexItem{ 231 "Info": { 232 {Name: "Version", Path: resturl.Version}, 233 {Name: "JSONSchema", Path: resturl.JSONSchema}, 234 }, 235 "NB configuration": { 236 {Name: "Get or Put NB configuration", Path: resturl.Configuration}, 237 {Name: "Validation", Path: resturl.Validate}, 238 }, 239 "ACL plugin": { 240 {Name: "IP-type access lists", Path: resturl.ACLIP}, 241 {Name: "MACIP-type access lists", Path: resturl.ACLMACIP}, 242 }, 243 "Interface plugin": { 244 {Name: "All interfaces", Path: resturl.Interface}, 245 {Name: "Loopbacks", Path: resturl.Loopback}, 246 {Name: "Ethernets", Path: resturl.Ethernet}, 247 {Name: "Memifs", Path: resturl.Memif}, 248 {Name: "Taps", Path: resturl.Tap}, 249 {Name: "VxLANs", Path: resturl.VxLan}, 250 {Name: "Af-packets", Path: resturl.AfPacket}, 251 }, 252 "L2 plugin": { 253 {Name: "Bridge domains", Path: resturl.Bd}, 254 {Name: "L2Fibs", Path: resturl.Fib}, 255 {Name: "Cross connects", Path: resturl.Xc}, 256 }, 257 "L3 plugin": { 258 {Name: "Routes", Path: resturl.Routes}, 259 {Name: "ARPs", Path: resturl.Arps}, 260 {Name: "Proxy ARP interfaces", Path: resturl.PArpIfs}, 261 {Name: "Proxy ARP ranges", Path: resturl.PArpRngs}, 262 }, 263 "Telemetry": { 264 {Name: "All data", Path: resturl.Telemetry}, 265 {Name: "Memory", Path: resturl.TMemory}, 266 {Name: "Runtime", Path: resturl.TRuntime}, 267 {Name: "Node count", Path: resturl.TNodeCount}, 268 }, 269 "Stats": { 270 {Name: "Configurator Stats", Path: resturl.ConfiguratorStats}, 271 }, 272 } 273 return idxMap 274 } 275 276 // Create permission groups (tracer, telemetry, dump - optionally add more in the future). Used only if 277 // REST security is enabled in plugin 278 func getPermissionsGroups() []*access.PermissionGroup { 279 infoPg := &access.PermissionGroup{ 280 Name: "info", 281 Permissions: []*access.PermissionGroup_Permissions{ 282 newPermission("/", GET), 283 newPermission(resturl.Version, GET), 284 newPermission(resturl.JSONSchema, GET), 285 }, 286 } 287 nbConfigValidationPg := &access.PermissionGroup{ 288 Name: "nbConfigValidation", 289 Permissions: []*access.PermissionGroup_Permissions{ 290 newPermission("/", GET), 291 newPermission(resturl.Validate, GET), 292 }, 293 } 294 nbConfigReadPg := &access.PermissionGroup{ 295 Name: "nbConfigRead", 296 Permissions: []*access.PermissionGroup_Permissions{ 297 newPermission("/", GET), 298 newPermission(resturl.Configuration, GET), 299 }, 300 } 301 nbConfigWritePg := &access.PermissionGroup{ 302 Name: "nbConfigWrite", 303 Permissions: []*access.PermissionGroup_Permissions{ 304 newPermission("/", PUT), 305 newPermission(resturl.Configuration, PUT), 306 }, 307 } 308 tracerPg := &access.PermissionGroup{ 309 Name: "stats", 310 Permissions: []*access.PermissionGroup_Permissions{ 311 newPermission("/", GET), 312 newPermission(resturl.ConfiguratorStats, GET), 313 }, 314 } 315 telemetryPg := &access.PermissionGroup{ 316 Name: "telemetry", 317 Permissions: []*access.PermissionGroup_Permissions{ 318 newPermission("/", GET), 319 newPermission(resturl.Telemetry, GET), 320 newPermission(resturl.TMemory, GET), 321 newPermission(resturl.TRuntime, GET), 322 newPermission(resturl.TNodeCount, GET), 323 }, 324 } 325 dumpPg := &access.PermissionGroup{ 326 Name: "dump", 327 Permissions: []*access.PermissionGroup_Permissions{ 328 newPermission("/", GET), 329 newPermission(resturl.ABF, GET), 330 newPermission(resturl.ACLIP, GET), 331 newPermission(resturl.ACLMACIP, GET), 332 newPermission(resturl.Interface, GET), 333 newPermission(resturl.Loopback, GET), 334 newPermission(resturl.Ethernet, GET), 335 newPermission(resturl.Memif, GET), 336 newPermission(resturl.Tap, GET), 337 newPermission(resturl.VxLan, GET), 338 newPermission(resturl.AfPacket, GET), 339 newPermission(resturl.Bd, GET), 340 newPermission(resturl.Fib, GET), 341 newPermission(resturl.Xc, GET), 342 newPermission(resturl.Arps, GET), 343 newPermission(resturl.Routes, GET), 344 newPermission(resturl.PArpIfs, GET), 345 newPermission(resturl.PArpRngs, GET), 346 }, 347 } 348 349 return []*access.PermissionGroup{infoPg, tracerPg, telemetryPg, dumpPg, 350 nbConfigValidationPg, nbConfigReadPg, nbConfigWritePg} 351 } 352 353 // Returns permission object with url and provided methods 354 func newPermission(url string, methods ...string) *access.PermissionGroup_Permissions { 355 return &access.PermissionGroup_Permissions{ 356 Url: url, 357 AllowedMethods: methods, 358 } 359 }