-
Notifications
You must be signed in to change notification settings - Fork 36
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
RPC provider #343
RPC provider #343
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #343 +/- ##
==========================================
+ Coverage 42.68% 44.43% +1.75%
==========================================
Files 44 50 +6
Lines 3730 4015 +285
==========================================
+ Hits 1592 1784 +192
- Misses 1951 2027 +76
- Partials 187 204 +17
☔ View full report in Codecov by Sentry. |
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.
Nice to see this shaping up.
I noticed there's a fair amount of flexibility and I'm not sure I appreciate why. For example, there are options to specify the HTTP content type and HTTP method used: whats the motivation for being so flexible when we are ultimately defining the contract?
In the case of content type, given we assume JSON does it make sense to even expose that in such a raw manner? (this makes me wonder if I really understand whats going on 🤔).
providers/rpc/http.go
Outdated
c.Logger.Info("rpc notification details", kvs...) | ||
} | ||
}() | ||
defer resp.Body.Close() |
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.
I don't recall how defer works but are you sure this closes the right handle given we reset the body on l.74?
(it may be the case that Go stores the point in memory it'll jump to on return at the time of defer
, hence I'm not sure if this is a problem)
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.
As im passing in resp *http.Response
, i am already handling the close in the caller so i think i will just remove this Close. Thoughts?
Thanks for the review, Chris. whats the motivation for being so flexible when we are ultimately defining the contract? With the goal of the RPC provider being to provide interoperability with existing/bespoke out-of-band systems, for me, flexibility is key. |
@jacobweinstock Sounds good, thanks for the explanation. |
providers/rpc/rpc.go
Outdated
// handle the response | ||
rp, err := c.handleResponse(resp, kvs) | ||
if err != nil { | ||
return ResponsePayload{}, err | ||
} | ||
|
||
return rp, nil |
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.
// handle the response | |
rp, err := c.handleResponse(resp, kvs) | |
if err != nil { | |
return ResponsePayload{}, err | |
} | |
return rp, nil | |
// handle the response | |
return c.handleResponse(resp, kvs) |
a7f6b65
to
1c74198
Compare
The idea of the RPC provider is to enable users the ability to interoperate with existing bespoke out of band system or as a stop gap for BMCs/protocols that bmclib does not have a provider for yet. Internal bespoke out of band systems will generally not be accepted into BMCLIB. So users can run a small web endpoint that implements the RPC contract. The RPC provider sends a request to the user's web endpoint. The web endpoint will then translate the call to the out of band protocol/tool/etc that is needed to communicate with the BMC. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
Hopping to help with understanding of the code base. Signed-off-by: Jacob Weinstock <[email protected]>
Reorg the Config struct to make clearer the different areas of concern. Remove internal package. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
This doc.go will detail the why of this package and its use. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
This was just experimentation. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
As bespoke out-of-band systems will require a high level of flexibility to interoperate properly, this provides even more flexibility around the RequestPayload while still maintaining a simple contract for the bmclib. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
Improvements for cleaner/clearer code. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
This is more core to the provider than the request. Used to submit the request not configure the request, so to speak. Signed-off-by: Jacob Weinstock <[email protected]>
Rename interface{} -> any. This change is compatible back to Go 1.18. Signed-off-by: Jacob Weinstock <[email protected]>
The struct name was changed so this updates the receiver variable to match. Signed-off-by: Jacob Weinstock <[email protected]>
Clarify its use with an example. Signed-off-by: Jacob Weinstock <[email protected]>
Let the caller handle the close. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
This guards against dos attacks that might send very large responses. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
1c74198
to
cc82aad
Compare
Signed-off-by: Jacob Weinstock <[email protected]>
Check status code and response payload in the Open method to validate the endpoint is conformant with the response contract. Update checking of the response error code as well as if it is nil. This will make sure we dont error out when a response contains a value for the error instead of just nil. Signed-off-by: Jacob Weinstock <[email protected]>
Signed-off-by: Jacob Weinstock <[email protected]>
Reading from io.Readers and then creating a nop closer and dealing with closing the readers was more difficult than it needed to be. Signed-off-by: Jacob Weinstock <[email protected]>
providers/rpc/rpc.go
Outdated
} | ||
defer resp.Body.Close() | ||
respBuf := new(bytes.Buffer) | ||
if _, err := io.Copy(respBuf, resp.Body); err != nil { |
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.
I think this may still be at risk of a DoS because Copy
will read everything from Body
into the buffer. That could consume a CPU and chew threw all available memory.
I think the only way to safely read is to chunk (https://pkg.go.dev/io#CopyN) checking the total bytes read as we go.
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.
ah yeah, fair. i'll use CopyN
and move the copy below the content length check.
Moving the response body copy to after the content length check and only coping the resp.Contentlegnth should give us more defense against malicious actors. Signed-off-by: Jacob Weinstock <[email protected]>
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 efforts here 🚀
What does this PR implement/change/remove?
This adds an RPC provider. The idea of the RPC provider is to enable users the ability to interoperate with existing bespoke out of band system or as a stop gap for BMCs/protocols that bmclib does not have a provider for yet. Internal bespoke out of band systems will generally not be accepted into BMCLIB.
So users can run a small web endpoint that implements the RPC contract. The RPC provider sends a request to the user's web endpoint. The web endpoint will then translate the call to the out of band protocol/tool/etc that is needed to communicate with the BMC.
Checklist
The HW vendor this change applies to (if applicable)
The HW model number, product name this change applies to (if applicable)
The BMC firmware and/or BIOS versions that this change applies to (if applicable)
What version of tooling - vendor specific or opensource does this change depend on (if applicable)
Description for changelog/release notes