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
dns/ddclient: add Netcup DNS API #3549
Conversation
This is a new DynDNS plugin for the DNS API of the German hosting provider Netcup. I have created this plugin to my best knowledge, trying to understand the existing new ddns client code. Me and my friend have tested this on our own installations (ARM and x86) and we believe it works well. However, I am not so happy with the naming of the input fields. I would have loved to specify my very own custom fields, but instead I had to re-use as many fields as possible. It would have been great if there had been a way that my plugin can state which fields it requires, but instead I am stuck with what is already there. Anyway, I am happy for any remarks and will gladly make any necessary changes to get this accepted. |
<Required>N</Required> | ||
<mask>/^[^\n]*$/</mask> | ||
</netcupAPIKey> | ||
<netcupSetTTL type="BooleanField"> |
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.
TTL will be added in a more generic way in https://github.com/opnsense/plugins/pull/3550/files#diff-ba4d24cee94fcdc665a4223826a1daea10fde3e20971b1e4865ee261d8e2b5f4R174
we should try to avoid service-specific naming
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.
TTL is in master now
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 have rebased my code against latest master and made the following changes:
all Netcup related fields were removed. The plugin now only uses existing fields.I have kept the API key password field separately, because- it's just so much more intuitive and the user has a help text directly there about the other fields without having to go to the Wiki
- There is already a provider specific field (resourceId). Why not have this one?
- The field is very easily hidden if not needed
- some polishing (removed unused exports, better logging and parameter checking)
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.
It would probably make more sense then to use user+pass as API key+pass and move customer to resourceID. But I think it's required and the GUI will not require it in this case? It needs some sort of constraint added but we can do that post-merge.
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.
Uh, that would be even more confusing, IMHO.
There is a service specific field for the azure plugin, so why can't another plugin have it's own specific field, too? Yes, with more plugins coming up this can clutter the configuration, I agree.
But abusing an already very specific field for yet another specific purpose is IMHO not a good way forward.
I still believe that every service should have it's very own custom fields with an exact help of what they are for. That would be the best option. But I guess that is not possible with the way the framework works, right?
In that case let me propose another way:
Get rid of all service specific fields and introduce a couple of general purpose fields. If a service then needs some special configuration, it can use those custom fields. These would then all be documented in the Wiki.
Does that sound like a way forward?
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 can't follow. You might know that it's common that some Web APIs require pairs of secrets. I have the feeling you are not really reading what others are writing. Please explain: Why is it okay to introduce a second visible field "resourceID" instead of concatenating it's value into the user ID field, but it's not okay to introduce a second invisible field "key" or "client secret"? Can you please come up with an logical explaination for that?
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.
Let’s try to keep this between author and reviewer. It’s hard enough to follow as is. 😉
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.
Curly060, can I be become Co-Author? Otherwise I'm not accept here.
Every DDNS has the same problem:
- Determine the As-Is value (= quering the master DDNS server)
- Determine and monitor the To-Be value
- Update the value if needed
Only step no 3 is different for different providers. For that reason it is a good idea to have one OPNSense plugin for all DDNS tasks and sub plugins for the different provider. The proposal to come up with an own OPNSense plugin for Netcup is for sure an antipattern. The discussion for a solution for the missing secret field is blocked. So I cannot see a possible innovation progress here.
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.
Dude, nothing is blocked. Two proposals are open for implementation. If you think the suggestion to create a separate plugin is overkill then I don’t disagree. I was merely pointing out when it makes sense to use „netcup“ specific fields and when it doesn’t.
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.
Let's come to an end with this. I have now added a field called "clientSecret" of type "password" with label text "Additional client secret, e.g. an API key". Now the field has nothing to do with Netcup at all, except that the Netcup plugin is currently its only user. But since the name is quite generic, this might change with future plugins coming up. Plus there are already fields that are provider specific and have generic names (ttl, resourceId). So I think this is a compromise between usability and maintainability.
Is the current form acceptable now?
@@ -110,6 +110,14 @@ | |||
<Required>N</Required> | |||
<mask>/^[^\n]*$/</mask> | |||
</password> | |||
<netcupAPIKey type="UpdateOnlyTextField"> |
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.
API key is usually the password and the user name is left blank
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 to clarify:
The Netcup DNS API requires a login which then returns an API Session ID. For the login the following input is required:
- customer number
- API password
- API key
The closest match to the existing fields were:
- customer number => username
- API password => password
- API key => no existing field, hence the introduction of a new field
It would also be possible to do something like this:
Enter both, API key and API password into the existing password field, separated with e.g. colon:
username field: :
The code could then split(':') the password field and get API key and password from it. However, this would require some documentation somewhere.
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.
Enter both, API key and API password into the existing password field
That would be my preference as well. Docs are here and a special note for cloudflare is there already: https://docs.opnsense.org/manual/dynamic_dns.html#provider-specific-configuration
If the API key has a fixed length input without separator would be possible as well.
d77d624
to
6c9e00d
Compare
259b8b0
to
c16ad72
Compare
Would be very interested in using this PR implementation. Is this still under active review after the discussion? |
The merge conditions have been laid out. Adding a new field is not an issue but using the API user as password and adding an API key field named clientSecret is highly counter-intuitive. |
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.
See other comment.
I looked at the code: "using the API user as password " sounds like a misunderstanding. The request uses the standard fields username and password perfectly well: username contains the customer number (Netcup username, which is not a secret password), and password contains the netcup API password (which is a secret password). Netcup requires an additional client secret (API Key) and for that the author introduced a new generic field for a client secret. Sounds exactly as required? |
To me this makes no sense at all:
And here we are debating the choices of one provider but making a decision forward for ALL possible providers in the future. |
Perfect mapping! But even if it does not make sense to you, the mapping does not belong to ALL possible providers, it belongs to the netcup plugin only. Till now you've not been able to explain you concerns. You are rejecting for no transprant reason. I really like to have that feauture as well. The branch works perfectly in my setup and is very well designed and mapped according to netcup requirements and according to generalizability of the chosen new field. |
let's agree to disagree, you can build your own software if you do want to release something that doesn't match our standards, just don't expect us to merge and maintain code in these cases. end of discussion until requested modifications are made. |
A standard is something that is written down and results can be verified against. Nobody explained what the criteria is to solve that problem. We all can be lucky that there is more contributors. You like to have some changes? Then you must explain it! You you are just rejecting. End of discussion? Wow, mighty person you are. Create a standard, write it down and then we can go further. |
@Sumpfdotter well, we did write down quite a lot, also about our standards and development workflow (https://docs.opnsense.org/), what did you do in the meantime that would help others?? An empty github profile and complaining about other peoples efforts. Wow... Feedback provided is mostly about normalization of data, which is quite a generic theme in software engineering. A lot of books have been written about these subjects, usually it's not needed to repeat those. Consider this my last comment, I still don't mind if someone is willing to do the work needed, in the meantime, please be so kind to stop wasting other peoples time. |
Req 2023-08-17-Fichtner-1: "TTL will be added in a more generic way" --> resolved by Curly060 From that point on, wrong aspects has been used for rejection: "An empty github profile and complaining about other peoples efforts" --> now it becomes personal? For you, human beings are defined by the content of the github profile only? You think there are no other fields where humans can become worthy? Let's focus on the solution I'd suggest ... |
best reread your own response.
Giving you some time to cool off now. |
Could we please take the heat out of this discussion and start over? We have somehow lost the focus. This name is by no means unusual (in fact, e.g. in Azure it is quite common) and now the field even has the potential to be used in future DDNS plugins. It is in no way any more "harmful" than "resourceId" (which is provider specific) or "ttl" (which was AWS specific, but with the intention to be used by future plugins, which is exactly what happens with this plugin now). That was my commit c16ad72 from September 2023 and is the current state. IMHO it does reflect everything that had been discussed up to that point back then, so I had asked if this new commit is acceptable but then never received any feedback. So what exactly is wrong with the current state of the commit and what needs to be changed for this to be accepted? I see that "changes are requested", but it is no longer clear to me what that change should be. |
Sure, the most important consistency comment is the use of username/password. For all other machine to machine communications (including our own api) the key+secret combination equals username+password. Which in your case means the customer nummer is the one missing (and doesn't have a logical existing spot). Some style cleanups might be needed in the python script itself, but I don't mind merging and skimming the code myself and letting you retest (as I don't have an account for this service). How we ended up with other people commenting PR's trying to force things in still under review is beyond me, but apparently that's sadly how it works these days. Eventually if it breaks at some point, in our experience, complaints go to the maintainer. I guess I can only advise people to read into opensource before using it (I personally found this book on the subject quite enlightening https://www.amazon.com/Working-Public-Making-Maintenance-Software/dp/0578675862) |
Thanks, I am glad we can continue on this. Let's try one more time to describe the situation and find a solution: In Netcup terminology the username is the customer number. For example if you go to the Netcup Customer Control Panel (CCP), you'll see it: It's a standard login page: username and password. Only that Netcup calls their username field "customer number". If it was possible to use their DNS API with just this, we would not even have had a discussion at all. We would have simply used username+password. Agreed? But in order to use their DNS API a second secret is necessary. In netcup terminology they call this "API-key". You need to create it inside CCP.
So that's two secret fields. Currently we have only one available in the GUI. So how to enter two secrets? There was the idea to put both, the PW and the client secret into the existing PW field. However, that has quite some implications: The new field solves all of this and I believe the mapping in the GUI is then quite intuitive. So to sum up: |
Let's try and cut to the chase here for the third time: Fine, but no. |
Yeah, let's. Please just answer precisely the following question: In which fields shall I put
so that this pull request becomes acceptable? Thanks. |
Below a copy from the code in the PR:
Which matches:
simple, easy, just like the rest. |
Hi Ad! Thank you for this idea. It indeed is quite simple, but not feasible. With your idea, the value of the field „API Key“ becomes visible to the user: |
I think we should discontinue this effort to integrate into os-ddclient then. I said before I’m not against adding a custom plugin for a single provider with all of its ups and downs and idiosyncrasies. |
And I explained that dynamic DNS has so much in common (determining current IP, comparing IP and triggering) that it'an anti-pattern to double that up. You never commented on that. |
Dear OPNSense organisation. You won: I spent hours and hours to support you in that question with tests, reviews, researches, explanations and moderations. This post ist my last contribution to your organisation. You are basically rejecting a community pull request which adds a new functionality in a way that no other existing functionality is impacted - I reviewed it and I tested it. There is no change to all other plugin-ins. At the same time, your own solution for Azure as shown impacts all other plugins. First you rejected the committer because he in your opinion does not fulfil your high standards - which was never explained where exactly. And now you are even rejecting the whole problem as incompatible with your solution, ignoring that the committer is just about requesting a pull which proves that it's possible to add that function without any impact. Translation for this is: You're accepting your own contributions even if they are not mature, and you reject the community contributions even if it adds new requested features without impact to your existing parts. We're here on GitHub which requires by statutes organisations to be open for community contributions. I hope that it's only one user and maybe your organisation changes it's mind some day. Till that day, you will be lucky that you're losing my support. |
The fix is simple, all other providers use the same semantics, username (key) + password (secret) in combination with whatever is vendor specific (same is the case for Azure by the way, where resourceId is specific). We can debate semantics forever, but I wasn't planning on joining. At the end of the day, the settings being entered are only visible by the admin. A very simple fix would be to follow the reasoning which was used for the rest of this plugin, Alternatively creating a specific plugin is also acceptable. A lot of vendors ship their own client tools. @Sumpfdotter I understand you are disappointed, but am going to make a final request to communicate normally and let the contributor handle feedback instead of trying to hijack the PR with more noise than needed. @Curly060 is free to change the PR as discussed, I am still willing to spend some time to cleanse the code where needed. The way you are to interacting on these tickets increases the chances that people like myself just give up and walk away..... |
Netcup is a German hosting provider who offers an API for DNS manipulation which this plugin makes use of, see: - Wiki: https://www.netcup-wiki.de/wiki/DNS_API - Technical documentation: https://ccp.netcup.net/run/webservice/servers/endpoint.php
Hi Ad, thanks. This was the first very clear answer of you guys to me in this whole discussion that finally made me understand what the problem is: Well, it's not. But all arguments are exchanged and it is clear to me now that you prefer to break semantics in this case as long as it fits to what's already there. I will not argue with that. Your product, your choice. But please also understand that I will not create a plugin that will show that secret already in the DynDNS Accounts overview (and it would: the username (aka API key) is shown in the Accounts tab). So the only way forward I see is to go back to a proposal that in the beginning of this discussion Franco had described as "That would be my preference as well". It's certainly not my preference, but it's a compromise and it does work: I have put API-Password and -secret into one field, the password field, separated by a colon. If the colon is part of the PW or API key, the user will have to escape it with a backslash. That's awkward for the user and it does require some explanation in the Wiki, but again, Franco had said that's fine. And hey, it does fulfill all requirements:
No new fields, just one new self contained class in this PR (and a visibility toggle for the TTL field). That's the current state and it is going to be my last attempt on this. I have jumped through quite some hoops here trying to get this right for everyone (you, me and the users of the plugin). I do this in my spare time in the hope to help others and as a way to say "thank you" to the project but at one point even my patience runs out. Awaiting your decision. Regards, Curly060 P.S.: Even though I shouldn't, please allow me one remark: To me it did not feel that Sumpfdotter "hijacked" anything here. Albeit sometimes really lengthy, I found his explanations very detailed and useful. |
I've cleaned up the code and put it in a new branch on our end https://github.com/opnsense/plugins/tree/ddclient_netcup If you can validate the workings of f087d6e , we can merge it if it still works. As I don't have an account, I can't try this myself. |
That's great. Thanks! I did find a couple of small bugs. You can find the fixes here: With those patches applied it works. About your additional check in line 178: That broke the logout method, because for the logout method the responsedata field is empty and thus this expression will evaluate to False and then an exception was thrown, even though the logout was successful. It is definitely enough to just check for this: Why? The API also has a SOAP endpoint and from the WSDL it is clear that there is always exactly one responsedata field. So if the API returns "success" you can rely on this field to be present (but possibly be empty). Then there are a couple of things that may or may be not problematic, so I have not fixed those yet: creating hostRecord
Now hostRecord is no longer a copy of matchingRecords[0]! This has side effects:
In practice probably not a problem, but I find making an explicit copy more robust. About the escaping |
@Curly060 I'll add the fixes to the branch, let me provide feedback to the open issues in your comments first.
Ah, clear, missed the logout spot. This also means
Missed the intention here, but we coulc easily fix that with
There are pro's and cons there indeed, usually, if the intention is to only modify a selection of data, we would only send the changed ones, but that also depends on the other end accepting partial data. When partial data is not accepted and new fields are added later, you might want to return them as is anyway.
If a separator is used, you need to escape it (as your code did as well). When there is a character never used in their api key+secret combination (for example imported 620737f including the changes discussed. |
About escaping: To my knowledge currently Netcup only generates PWs and Keys with the following characters: 0-9, a-z, A-Z With the CSV solution we'd be prepared. I have made a diff against your latest changes which uses the csv module: In any case, I have successfully tested both: Edit: Corrected what I said about KeyError. There is no KeyError. |
I would go for a pipe sign A key error sounds a bit weird as both |
A pipe is also fine. And ignore me about the KeyError, wrong test setup, you are right, it will not happen (I had extracted the code to a separate standalone file to test more easily all edge cases and forgot the init part.) |
Ok, I'll change the code, merge it and leave a note in the documentation about the custom input. |
Netcup is a German hosting provider who offers an API for DNS manipulation which this plugin makes use of, see: