Comments (25)
Confirmed @bigfootjon 's code works. Less monkey patch, more direct hacking...
my certbot.hover.sh is looking like
TOKEN=$(oathtool -b --totp 'MY_TOTP_SECRET')
PROVIDER_CREDENTIALS=("--auth-username=MY_USERNAME" "--auth-password=MY_PASSWORD" "--auth-token=${TOKEN}")
I think a pyotp integration might be appropriate? --auth-totp-secret instead of --auth-token
#539 #716 #771 #884 seem to be covered by this as well
from lexicon.
Hello @Sudrien, I fixed the issues that have been caught, you can test again.
from lexicon.
Same problem encountered here.
I thought toggling it off in account settings would do the trick but it just remains on, reading further into it I noticed they state it's now mandatory. Frustrating!
I've contacted Hover, if no change (which I highly doubt unfortunatly...) I'll change provider.
from lexicon.
Just to update... I moved my domain to Google and now using a service called ddclient.
Not sure what OPs use case is but for me I simply needed a way to update my domain to reference my external dynamic IP.
ddclient does the job beautifully and seems to be very popular and well maintained/documented.
I wish I had discovered it sooner. It took me a long time to get the (now broken) Hover script working in this way.
from lexicon.
Hey - I'm the original contributer of the Hover provider in lexicon. I got a nice surprise when my certbot and wildcard certificates failed!
I'm also going to contact Hover support, but I suspect this will also drive me to change providers 😞
from lexicon.
I contacted Hover support, and they were not immediately helpful. I switched to using Google Cloud for DNS becuause that's what I use in my day job. It costs me $0.01/day or $0.30/month so its almost free. I'm sure there are other free DNS providers to switch to.
from lexicon.
It is actually possible to login with 2fa using dns-lexicon
I've monkey-patched my local implementation to do this:
# The provided _authenticate function does not provide authentication
# for 2fa-enabled accounts. This shim does that
def _new_authenticate(self: hover.Provider) -> None:
# Getting required cookies "hover_session" and "hoverauth"
response = requests.get("https://www.hover.com/signin")
self.cookies["hover_session"] = response.cookies["hover_session"]
# Part one, login credentials
payload = {
"username": self._get_provider_option("auth_username"),
"token": None,
"password": self._get_provider_option("auth_password"),
}
response = requests.post(
"https://www.hover.com/signin/auth.json", json=payload, cookies=self.cookies
)
response.raise_for_status()
# Part two, 2fa
payload = {
"code": self._get_provider_option("auth_token"),
}
response = requests.post(
"https://www.hover.com/signin/auth2.json", json=payload, cookies=self.cookies
)
response.raise_for_status()
if "hoverauth" not in response.cookies:
raise Exception("Unexpected auth response")
self.cookies["hoverauth"] = response.cookies["hoverauth"]
# Make sure domain exists
# domain is stored in self.domain from BaseProvider
domains = self._list_domains()
for domain in domains:
if domain["name"] == self.domain:
self.domain_id = domain["id"]
break
else:
raise AuthenticationError(f"Domain {self.domain} not found")
hover.Provider._authenticate = _new_authenticate
If this looks like a reasonable implementation I'd be happy to open a PR
from lexicon.
Ok guys, let's tackle this.
So basically it seems that we have two approaches:
- either exposing an OTP generated outside of Lexicon through a new flag like
--auth-token
- or generate the OTP directly in Lexicon using a provided secret through a new flag like
--auth-totp-secret
and the integration of a Python OTP library.
The issues review from Sudrien seems to indicate that OTP could be used in other providers, in place of dedicated static application credentials. Also pyotp
seems a very light library with no dependency and large Python compatibility and activate maintenance. I am usually reluctant to add a dependency either globally to avoid big dependency graphs, or for a specific provider given the added complexity to handle this user-side. But here it seems to be a reasonable move.
So I will create a PR for hover
with the approach proposed by @bigfootjon + the flag and pyotp
integration proposed by @Sudrien.
Then, since I have no active account for Hover, I would like that one of you test the updated provider and generate the new set of cassettes for the integration tests. Sounds good to you ?
from lexicon.
Unfortunately I’m traveling for the next few weeks so I’ll be unable to test until then, but the code looks conceptually correct to me
from lexicon.
Sorry, more of a rubygems person usually
pip install git+https://github.com/AnalogJ/lexicon.git@hover-otp
somthing worked
lexicon hover -h
New option shows
PROVIDER_CREDENTIALS=("--auth-username=MY_USERNAME" "--auth-password=MY_PASSWORD" "--auth-totp-secret=MY_TOTP_SECRET")
Note: MY_TOTP_SECRET should have no whitespace, according to quick pyotp test - what breaks when I have it in? Test this later
trying this with my test call for last night...
manual-auth-hook command "/root/certbot.hover.sh auth" returned error code 1
Error output from manual-auth-hook command certbot.hover.sh:
Traceback (most recent call last):
File "/usr/local/bin/lexicon", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python3.9/dist-packages/lexicon/_private/cli.py", line 135, in main
results = client.execute()
File "/usr/local/lib/python3.9/dist-packages/lexicon/client.py", line 194, in execute
executor = self.__enter__()
File "/usr/local/lib/python3.9/dist-packages/lexicon/client.py", line 151, in __enter__
raise e
File "/usr/local/lib/python3.9/dist-packages/lexicon/client.py", line 143, in __enter__
provider = self.provider_class(self.config)
TypeError: Can't instantiate abstract class Provider with abstract method authenticate
....
Which seems to be about
def _authenticate(self) -> None:
in hover.py but switching it back gets rid of the error with no actual dns change, and thus challenge failure.
from lexicon.
Wait, switched to
def authenticate(self):
from
def _authenticate(self) -> None:
and removed
"token": None,
in the first call from hover.py and I'm getting success.
Doing the MY_TOTP_SECRET with whitspace test mentioned above...
manual-cleanup-hook command "/root/certbot.hover.sh cleanup" returned error code 1
Error output from manual-cleanup-hook command certbot.hover.sh:
Traceback (most recent call last):
File "/usr/local/bin/lexicon", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python3.9/dist-packages/lexicon/_private/cli.py", line 135, in main
results = client.execute()
File "/usr/local/lib/python3.9/dist-packages/lexicon/client.py", line 194, in execute
executor = self.__enter__()
File "/usr/local/lib/python3.9/dist-packages/lexicon/client.py", line 151, in __enter__
raise e
File "/usr/local/lib/python3.9/dist-packages/lexicon/client.py", line 144, in __enter__
provider.authenticate()
File "/usr/local/lib/python3.9/dist-packages/lexicon/_private/providers/hover.py", line 59, in authenticate
payload = {"code": self.totp.now()}
File "/usr/local/lib/python3.9/dist-packages/pyotp/totp.py", line 64, in now
return self.generate_otp(self.timecode(datetime.datetime.now()))
File "/usr/local/lib/python3.9/dist-packages/pyotp/otp.py", line 35, in generate_otp
hasher = hmac.new(self.byte_secret(), self.int_to_bytestring(input), self.digest)
File "/usr/local/lib/python3.9/dist-packages/pyotp/otp.py", line 52, in byte_secret
return base64.b32decode(secret, casefold=True)
File "/usr/lib/python3.9/base64.py", line 231, in b32decode
raise binascii.Error('Non-base32 digit found') from None
binascii.Error: Non-base32 digit found
So I'd suggest stripping all whitespace when feeding it into pyotp - as whitespace is often introduced to make human handling easier.
from lexicon.
My tests are all working as expected now, thank you.
from lexicon.
Hello @Sudrien, are you willing to go ahead and update the cassettes stored in the repository for Hover provider, that allows offline integration tests? It is basically about:
- setup a development environment: https://dns-lexicon.readthedocs.io/en/latest/developer_guide.html#add-new-tests-recordings
- add new tests recordings for
hover
: https://dns-lexicon.readthedocs.io/en/latest/developer_guide.html#add-new-tests-recordings
If not, my alternative is that you provide me some temporary credentials and I do it directly.
from lexicon.
I can handle one dump, unfortunately what I'm seeing is a bit beyond my python knowledge at the moment.
@adferrand, Assuming your commit email is current, I've sent login information for my second account.
from lexicon.
Yeah I can confirm that this PR works for me
from lexicon.
hi, i install via pip install dns-lexicon how to update to have this modify ? like pip install will update the existing one with the fix for that ?
from lexicon.
It is actually possible to login with 2fa using dns-lexicon
I've monkey-patched my local implementation to do this:
# The provided _authenticate function does not provide authentication # for 2fa-enabled accounts. This shim does that def _new_authenticate(self: hover.Provider) -> None: # Getting required cookies "hover_session" and "hoverauth" response = requests.get("https://www.hover.com/signin") self.cookies["hover_session"] = response.cookies["hover_session"] # Part one, login credentials payload = { "username": self._get_provider_option("auth_username"), "token": None, "password": self._get_provider_option("auth_password"), } response = requests.post( "https://www.hover.com/signin/auth.json", json=payload, cookies=self.cookies ) response.raise_for_status() # Part two, 2fa payload = { "code": self._get_provider_option("auth_token"), } response = requests.post( "https://www.hover.com/signin/auth2.json", json=payload, cookies=self.cookies ) response.raise_for_status() if "hoverauth" not in response.cookies: raise Exception("Unexpected auth response") self.cookies["hoverauth"] = response.cookies["hoverauth"] # Make sure domain exists # domain is stored in self.domain from BaseProvider domains = self._list_domains() for domain in domains: if domain["name"] == self.domain: self.domain_id = domain["id"] break else: raise AuthenticationError(f"Domain {self.domain} not found") hover.Provider._authenticate = _new_authenticateIf this looks like a reasonable implementation I'd be happy to open a PR
can i see all your code please ? i don't have "hover."
from lexicon.
Hover is just the provider provided by lexicon. Its import path has moved around over time.
I deleted this code since a new release was made with similar code
from lexicon.
Hover is just the provider provided by lexicon. Its import path has moved around over time.
I deleted this code since a new release was made with similar code
so why my [dns-lexicon] hover api isn't working ?
from flask import jsonify
from lexicon.config import ConfigResolver
from lexicon.client import Client
def dohoverapi(nome,ip):
lexicon_config = {
"provider_name" : "hover", # lexicon shortname for provider, see providers directory for available proviers
"action": "create", # create, list, update, delete
"domain": "x", # domain name
"name" : nome,
"content" : ip,
"type": "A", # specify a type for record filtering, case sensitive in some cases.
"hover": {
"auth_username": "y",
"auth_password": "z"
}
}
config = ConfigResolver()
config.with_env().with_dict(dict_object=lexicon_config)
client = Client(config)
results = client.execute()
dohoverapi("test","x.y.z.k")
response : 401 Client Error: Unauthorized
from lexicon.
Please look at this PR: #1718
or this documentation: https://dns-lexicon.readthedocs.io/en/latest/configuration_reference.html#hover
you need to pass a new option
from lexicon.
Please look at this PR: #1718
or this documentation: https://dns-lexicon.readthedocs.io/en/latest/configuration_reference.html#hover
you need to pass a new option
thanks for quick reply :
- i don't have "auth_totp_secret" in my code i install via pip install maybe isn't officially relesed ?
- where i can take this param ?
from lexicon.
- Yes it is officially released, please refer to the release notes: https://github.com/AnalogJ/lexicon/releases/tag/v3.15.0
- Not sure I understand this question
from lexicon.
auth_totp_secret <- what i have to put here ?
from lexicon.
idk guys i have to do in a different way :
with auth_totp_secret => xyz=== 422 (Unprocessable Entity)
i do :
in hover.py :
in __init ()
otp_uri = 'otpauth://totp/Hover:name?secret=secret&issuer=Hover'
self.totp = pyotp.parse_uri( otp_uri )
in authenticate():
payload = {"code": self.totp.now()}
now it work but everytime hover.com send me a mail new access
from lexicon.
Your auth_totp_secret is the value of “secret=“ in your URL
from lexicon.
Related Issues (20)
- DuckDNS.org API support HOT 1
- Docs specify wrong environment variable for tldextract cache
- lexicon cannot find the route53.py HOT 3
- GoDaddy listing records fails if given --content option
- Add Technitium DNS server API HOT 4
- importlib-metadata package not needed HOT 2
- Can't use lexicon with pending Cloudflare domains
- Cloudflare - 405 while deleting a TXT record (cloudflare.py#L172-L183) HOT 1
- Error in certbot-dns-ovh using lexicon HOT 10
- Wrong requests requirement HOT 2
- Gandi API key method is deprecated HOT 2
- certificate domain tld is added to gandi request since dnsrobocert 3.25.0
- Add all-inkl as supported Provider
- DDNS provider is not responding to error conditions correctly
- Cannot make SRV on CloudFlare HOT 1
- Add support for dynv6.com? HOT 3
- RFE: use `zoneinfo` instead of `pytz` HOT 1
- [easyname] provider broken (security code/2FA, REST API) HOT 5
- Update of docs
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lexicon.