-
Notifications
You must be signed in to change notification settings - Fork 701
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
[PROPOSAL] policy: Enable to define policy as go plugin #1577
base: master
Are you sure you want to change the base?
[PROPOSAL] policy: Enable to define policy as go plugin #1577
Conversation
`options *table.PolicyOptions` provides the additional information about sender | ||
router for example. | ||
|
||
The return value of `*table.Path` should be the updated path if successfully |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you return if you want to reject the prefix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just returning nil
should work as reject.
generated policy plugin (`.so` file) with `plugin-path` in | ||
`[[policy-definitions]]` section. | ||
|
||
Example: Attach `policy_a.so` to global RIB as "import policy" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you reload it at runtime if there is any change in the policy? How?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay. It’s a troublesome...
When reloading the confirmation, GoBGP will determine the configured values are updated or not before reload API. Then if the configuration file is not changed, even if the plug in is updated, GoBGP can’t detect change of the plug in's implementation.
So if we need to update and reload the plug in, it is required to change the path to plug in or its name.
For example, policy_a.1.0.so
to policy_a.1.1.so
or appending the updated timestamp or date.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick answers. I think renaming things and changing the path is fine. Might be worth adding a note to the README so people is aware this is how policies are updated when you are using this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thanks a lot! I will add description about how to update the policy plug-in and how to reject the given prefix.
@@ -889,6 +889,14 @@ module gobgp { | |||
|
|||
} | |||
|
|||
augment "/rpol:routing-policy/rpol:policy-definitions/" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you have to update this as well? https://github.com/osrg/gobgp/blob/master/api/gobgp.proto#L1076
I tried rebuilding my grpc bindings for python and the following didn't work:
>>> import gobgp_pb2
>>> policy = gobgp_pb2.Policy()
>>> policy.name = "a_policy_that_uses_go_code"
>>> policy.plugin_path = "/path/to/policy.go"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Policy' object has no attribute 'plugin_path'
Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I haven't yet consider the implementation for the gRPC API, I did just "by using configuration file" case. I will investigate what are required to support this feature on the gRPC API and update PR.
d081270
to
95b2967
Compare
@dbarrosop Thanks for reviewing my patch! |
thanks to you for the patch. I might be a bit short on time to test the gRPC interface in the next couple of weeks but I will try |
For more programmable policy definition, this patch enables to define policy as "plugin" (requires Golang 1.8+) and apply arbitrary rules by implementing policy plugin. Signed-off-by: IWASE Yusuke <[email protected]>
95b2967
to
7fd1889
Compare
What problem is this pull request trying to solve? I'm a bit concerned about adding the ability to load arbitrary code via an RPC. An attacker that gains access to RPC calls today can only impact BGP peer sessions, which likely have their own peering policies to limit the scope of accepted advertisements. With the attacker could start a remote shell as the GoBGP user and look for potential privilege escalations. In addition plugins can never be unloaded, further dwindling the benefits of remote management. Plugins also introduce programming errors for policies at runtime as well as allows writing policies that could remove determinism. One run of GoBGP given the same set of policies may not yield the same set of paths. Configuration through the current policy management do not suffer from these same problems. It's not my place to gauge value of features, I'm not against having plugins. It may solve some interesting use cases for people. I strongly believe it should not be part of the RPC. The plugin path should be a command line flag / env var like "--plugin-path" - that is loaded once at startup. Each plugin could have a name of some type, that is referenced by the policy config instead of a real physical file path. I suggest a "name" because I would like to avoid any file references in the RPC- as then you need to be careful of directory traversals |
@cstockton Hi, First this PR tried to provide the more flexible way to describe policies rather than OpenConfig. Using OpenConfig is good to fit the standard, but I think it is complex to optimize what we want to do with the policies. So I tried to provide the programmable way to do "arbitrary" actions. Second, this approach is very experimental and as you pointed out, this PR seems to have some security problems. |
I'd like you to consider the attack vector for this particular feature. The grpc endpoint allows you to specify the local path of a plugin that can act as policy. This means for an attacker to do any harm it needs to compromise the server first and be able to upload code prior to change the policy. In summary, you need to compromise two systems; the server and whatever is securing the grpc endpoint. Also, if an attacker can upload arbitrary code to your server you have bigger problems than their ability to influence your BGP policy and it also invalidates the premise that passing it via local configuration or the command line as everything the attacker needs to do is upload the file and restart the service or wait until an operator does. |
@dbarrosop I believe you are misinformed on multiple fronts based on your response and the lack of security considerations in the code itself. This is completely okay, it's why I'm here having this dialog with you. Lets start by reasoning through your first counter argument, which is essentially this:
This argument can be proven false quite simply. The number of potential attack vectors is now the currently undefined total number of mechanisms to put a file on the file system. This is immeasurable risk that will vary greatly across each system configuration. Meaning in order for your feature to be secure you rely on factors that aren't constants you control. An attacker only has to find a service that puts memory they control anywhere on the file system, this is undefined, but lets take some concrete examples:
A motivated attacker may not find a way to get a file on the file system, but that isn't an assumption you may make when writing software responsibly. We have to assume they may find a way and measure the consequence. Compromising of systems is usually done through multiple steps, small escalations in privilege that start with something innocent and build up using assumptions made in this pull request. I hope the GoBGP authors reconsider being a privilege escalation stepping stone. Security aside:
|
If your counterarguments are basically (1) a personal attack and (2) designing an inherently insecure system that is a disaster waiting to happen and that would make cry any security engineer consider me out. You clearly don’t have any interest in anything other than shutting this down. P.S.: if security was really the concern we would be discussing how we can sign and validate the code or other solutions like that |
@dbarrosop First I'm sorry I've made you feel like this was a personal attack, that wasn't my intention. If you could please reach out to me on the GoBGP slack I would be happy to remove any offensive portions of my post. Second I know you put a lot of work into this so I understand how having someone challenge the technical merit of part of it may be discouraging. But I assure you shutting down your pull request as a whole is not my intention here. I would be happy help you shape this into something that is a good compromise between security and your use case. If you're not interested in working together on this keep in mind I am not a GoBGP maintainer, just a proud user of this fantastic project. So providing some strong counter arguments against my opinions here to help them make an informed decision could be another avenue to take. Maybe you have an example of another large project which allows loading Go plugins via an remote API? We could review issues and pull request to see what kind of engineering rigor went into the feature and how they mitigated security risks. Finally for your p.s. - I assure you security is my only intention here. I did not provide any methods to mitigate risk because I feel the trade-offs for all of them are inadequate given the critically of the systems GoBGP is used in. I feel the security standards of a networking control plane should have a very high bar. A couple things that may come to mind for you and reasons I'm opposed to them: Code SigningI feel the additional complexity added by requirements of secure code signing such as PKI, careful usage of crypto primitives, providing proofs for correctness and potentially adding new dependencies for a feature that few will use is a tough sell. If you did decide to go through the engineering rigor to deliver secure code signing and work through how to make sure GoBGP plugins are disabled by default I would be happy to reconsider my position. Restrict all plugin files to a specific directory (i.e.
|
Related to the discussion on Slack, this patch enable to define policy as Golang "plugin" (requires Golang 1.8+).