Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Link Style Settings #6

Closed
sempervictus opened this issue Jan 20, 2025 · 8 comments
Closed

Feature: Link Style Settings #6

sempervictus opened this issue Jan 20, 2025 · 8 comments

Comments

@sempervictus
Copy link

Thanks for setting this up - declarative interaction with the API is a much more sane approach than what we've been doing with a bespoke Ruby lib.

The link styling calls are fun, our imperative version is:

def set_link_style(node, iface, style_params = {}, path = @lab)
    link = get_node_link(node, iface)
    node_id = get_node_id(node)

    params = link.merge({
        "id" => "network_id:#{link['network_id']}",
        "node" => "#{node_id}",
        "interface_id" => "#{get_eth_id(node, iface)}",
    }).merge!(style_params)
    put_lab(params, path + '/nodes/' + node_id + '/style')
end

which calls

def get_node_link(node, iface)
    node = get_node_name(node)
    get_topology.find do |link|
        (link['source_node_name'] == node or link['destination_node_name'] == node) and
        (link['destination_label'] == iface or link['destination_interfaceId'] == iface or
        link['source_label'] == iface or link['source_interfaceId'] == iface)
    end
end

to figure out what's connected to what and then PUT the style params into the node API endpoint's /style target.
We use this in calls such as

def set_link_label(node, iface, label, path = @lab)
    set_link_style(node, iface, {'label' => label}, path)
end

def set_link_speed(node, iface, speed = '100G', path = @lab)
    raise "Invalid speed" unless  LinkStyle[speed]
    set_link_style(node, iface, LinkStyle[speed], path)
    set_link_quality(node, iface, LinkQuality[speed], path)
end

def set_link_locality(node, iface, locality = 'WAN', path = @lab)
    raise "Invalid locality" unless LinkStyle[locality] 
    set_link_style(node, iface, LinkStyle[locality], path)
end

which for a TF provider can be left to the user quite easily since everyone has their own way of representing link attributes.

Not sure how much of that logic belongs in your interface lib and how much goes into the provider but looks to me like UpdateNodeInterface could be expanded for this in the SDK and expose a clean interface to the provider to set style as a nested schema on the link.

@CorentinPtrl
Copy link
Owner

Hello, thank you for the proposal. However, I believe this is an EVE-NG Pro feature. I checked the EVE-NG api.php endpoints and didn’t find any /style endpoint. (I’m currently using the Community Edition)

@sempervictus
Copy link
Author

sempervictus commented Jan 20, 2025

I pinged RedFish to get you a license - will buy you one if they can't issue w/out a PO. You can find my email address in a bunch of metasploit modules if you just grep -ri through modules/ for this username or my handle (its in all of my commits). Will need non-public comms to exchange the licensing info i need to get you all of the features. You can also find me in their webchat thing, i often lurk in there since i keep comms with the devs (we've done a bunch of kernel and qemu stuff over the years).

Meantime, if you could scaffold the logic (i'm not great with the way structures are being defined here) to implement, i'm happy to test in our lab. We dont expose it to the WAN and i can't provide third parties access due to NDAs around what's in it but i write enough Go to be dangerous (offsec person, have to do a bit of everything) and probably get this over the finish line between engineering tasks.

@sempervictus
Copy link
Author

These should be the viable keys for the params hash to a link -

            "type",
            "source",
            "source_type",
            "source_label",
            "source_node_name",
            "source_interfaceId",
            "source_suspend",
            "destination",
            "destination_type",
            "destination_label",
            "destination_interfaceId",
            "destination_node_name",
            "destination_suspend",
            "network_id",
            "style",
            "linkstyle",
            "label",
            "color",
            "source_delay",
            "source_loss",
            "source_bandwidth",
            "source_jitter",
            "destination_delay",
            "destination_loss",
            "destination_bandwidth",
            "destination_jitter"

which you should be able to get from the topology endpoint (https://www.eve-ng.net/index.php/how-to-eve-ng-api/) when it dumps the JSON of all links. Our call for that is

        def get_topology(id = nil, path = @lab)
            get_lab(path + '/topology' + (id.nil? ? '' : "/#{id}"))
        end

If you don't already have a toplogy data type, might be handy to implement as a way to access their side of state structurally (when you go hard against their API, it can ... have issues. RedFish and crew have done tons of work to help with that over the last couple of years but its not 100% foolproof yet).

@sempervictus
Copy link
Author

Hello, thank you for the proposal. However, I believe this is an EVE-NG Pro feature. I checked the EVE-NG api.php endpoints and didn’t find any /style endpoint. (I’m currently using the Community Edition)

Actually, come to think of it... when i wrote that Ruby lib there was a ton of undocumented stuff as well which i had to MiTM out of the browser's interaction with EVE. Anything you can do in the browser you can do in the API, its just not necessarily all documented.

@CorentinPtrl
Copy link
Owner

Once I have EVE-NG Pro up and running, implementing those structures should be relatively quick. I noticed the EVE-NG API documentation isn’t very comprehensive; I usually dive straight into the source code it’s faster than making all the requests and dissecting everything one step at a time. I also noticed that their API didn’t respond correctly when I sent requests too quickly, but adding a mutex to handle one request at a time was enough to resolve the issue.

@CorentinPtrl
Copy link
Owner

I pinged RedFish to get you a license - will buy you one if they can't issue w/out a PO. You can find my email address in a bunch of metasploit modules if you just grep -ri through modules/ for this username or my handle (its in all of my commits). Will need non-public comms to exchange the licensing info i need to get you all of the features. You can also find me in their webchat thing, i often lurk in there since i keep comms with the devs (we've done a bunch of kernel and qemu stuff over the years).

Meantime, if you could scaffold the logic (i'm not great with the way structures are being defined here) to implement, i'm happy to test in our lab. We dont expose it to the WAN and i can't provide third parties access due to NDAs around what's in it but i write enough Go to be dangerous (offsec person, have to do a bit of everything) and probably get this over the finish line between engineering tasks.

If you'd like me to prioritize certain features over others, please create a separate issue for each feature so I can address them in order of priority.

@sempervictus
Copy link
Author

Once I have EVE-NG Pro up and running, implementing those structures should be relatively quick. I noticed the EVE-NG API documentation isn’t very comprehensive; I usually dive straight into the source code it’s faster than making all the requests and dissecting everything one step at a time. I also noticed that their API didn’t respond correctly when I sent requests too quickly, but adding a mutex to handle one request at a time was enough to resolve the issue.

My version for the actual dispatch of HTTP methods is gory manual stuff (part of why the Ruby lib was never published) but here's a taste of horror:

        def _call(uri, data = nil)
            # Cleanup URI
            uri = "/#{uri}" unless uri[0] == '/'
            uri = "/api#{uri}" unless uri =~ /^\/api/
            uri.gsub!(/\/\//,'/')
            # Build params
            params = {
                :url => @server + uri,
                :method => caller_locations(1,1)[0].label.to_sym,
                :headers => {
                    :content_type => :json,
                    :accept => :json
                },
                :cookies => (@cookies.dup || {}).merge({'html5' => '-1'}),
                :verify_ssl => @verify_ssl
            }
            params[:payload] = (data.is_a?(Hash) ? data.to_json : data) if [:post, :put].any? { |m| params[:method] == m }
            @last_params ||= {}
            @last_params[params[:method]] = params.dup if uri !~ /status$|login$/
            # Run request, retry 
            ctr = 0
            begin
                res = RestClient::Request.execute(params)
                @cookies.merge!(res.cookies)
            rescue RestClient::PreconditionFailed => e
                puts e
                puts e.backtrace
                ctr += 1
                raise e if ctr > 3
                logout
                sleep 1
                login
                session_info
                system_status
                retry
            rescue RestClient::BadRequest, RestClient::InternalServerError => e
                @last_error = e
                res = e.http_body
            end
            raise "#{res}" if res == "{\"code\":400,\"status\":\"fail\",\"message\":\"Failed to lock the lab (60061).\"}"
            return res
        end

@sempervictus
Copy link
Author

I pinged RedFish to get you a license - will buy you one if they can't issue w/out a PO. You can find my email address in a bunch of metasploit modules if you just grep -ri through modules/ for this username or my handle (its in all of my commits). Will need non-public comms to exchange the licensing info i need to get you all of the features. You can also find me in their webchat thing, i often lurk in there since i keep comms with the devs (we've done a bunch of kernel and qemu stuff over the years).
Meantime, if you could scaffold the logic (i'm not great with the way structures are being defined here) to implement, i'm happy to test in our lab. We dont expose it to the WAN and i can't provide third parties access due to NDAs around what's in it but i write enough Go to be dangerous (offsec person, have to do a bit of everything) and probably get this over the finish line between engineering tasks.

If you'd like me to prioritize certain features over others, please create a separate issue for each feature so I can address them in order of priority.

Roger, i think this is the top one. Will create lower priority ones for tracking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants