-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
(WIP) networking: Add support for OpenVPN #19363
base: main
Are you sure you want to change the base?
Conversation
subhoghoshX
commented
Sep 21, 2023
•
edited
Loading
edited
ca446c9
to
bec2e80
Compare
Greatly simplified config/cert generation, fetching to host machine and file upload tests. |
353 ms to 140 ms = 60.4% reduction I guess the refactoring was worth it... |
a687536
to
f97e6d7
Compare
Generating Deffie-Hellman params on the CI can be an interesting flake as generating the (prime) numbers can take anywhere from less than a second to more than a minute... |
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 had a first coarse look at the import and config file structure. I'm rather relieved to see that there is nothing fundamentally weird -- just some rather shallow and easy cleanups (see threads below). I did not look into the design aspect of this, that needs to wait until Garrett is back. I figure he has some ideas/opinions about the dialog and the optional import, and how to "merge" it with Wireguard to have a single "Add VPN" button. But let's get the technical underpinnings right in the meantime.
Thanks, this is great work!
@@ -144,6 +145,9 @@ export const NetworkInterfacePage = ({ | |||
} | |||
|
|||
function disconnect() { | |||
if (active_connection.Vpn === true) |
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 it be truthy without being true
? What other values can this have?
let isChecked = !!(dev && dev.ActiveConnection); | ||
if (active_connection && active_connection.Vpn === true) | ||
isChecked = true; | ||
else if (!active_connection) | ||
isChecked = false; |
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.
This is redundant and hard to understand. The if
overwrites the initial isChecked
in most cases. Please simplify using ??
and the duplicated/triplicated checks, and write as a single const
or an else
branch (for "active non-VPN" connection). This could also use a comment which cases exist.
<NetworkAction buttonText={_("Add VPN")} type='wg' /> | ||
<NetworkAction buttonText={_("Add OpenVPN")} type='openvpn' /> |
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.
This needs design. We deliberately called the initial button "VPN", not "Wireguard", as we anticipated that we're going to have more types. This somehow needs to get folded into "Add VPN".
pkg/networkmanager/openvpn.jsx
Outdated
const configFile = "/tmp/temp.ovpn"; // TODO: use a random name for temporary files | ||
await cockpit.file("/tmp/ovpn-to-json.py").replace( |
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.
You don't have to write that into a file at all. Build a string, and run it through pkg/lib/python.js's spawn()
.
|
||
// TODO: clean it | ||
async function ovpnToJSON(ovpn) { | ||
const configFile = "/tmp/temp.ovpn"; // TODO: use a random name for temporary files |
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 would recommend to not create that file name on the JS side, it's too much churn. Let the Python script create it using NamedTemporaryFile
, process it, read it, and return the JSON on its stdout (as it already does).
with open("${configFile}", "w") as ovpn_file: | ||
ovpn_file.write("""${ovpn}""") | ||
|
||
subprocess.run(["nmcli", "con", "import", "--temporary", "type", "openvpn", "file", "${configFile}"], stdout=subprocess.DEVNULL) |
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.
Please try if you can do file -
or file /dev/stdin
and pipe the ${ovpn}
data into the process; then you don't need the configFile temp file at all. Otherwise use a NamedTemporaryFile.
pkg/networkmanager/openvpn.jsx
Outdated
os.remove("/tmp/ovpn-to-json.py") | ||
subprocess.run(["nmcli", "con", "del", "temp"], stdout=subprocess.DEVNULL) | ||
`); | ||
const json = await cockpit.spawn(["python", "/tmp/ovpn-to-json.py"], { superuser: 'try' }); |
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 you want require
here, for a better error message.
pkg/networkmanager/openvpn.jsx
Outdated
const caPath = `${user.home}/.cert/${caFileName}-ca.pem`; | ||
const userCertPath = `${user.home}/.cert/${certFileName}-cert.pem`; | ||
const userKeyPath = `${user.home}/.cert/${keyFileName}-key.pem`; |
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.
Is ~/.cert an official NM or recommended OpenVPN path? That sounds rather sad, this stuff belongs into ~/.config/networkmanager or something ovpn specific.
pkg/networkmanager/openvpn.jsx
Outdated
<Name idPrefix={idPrefix} iface={iface} setIface={setIface} /> | ||
<FormFieldGroup | ||
header={ | ||
<FormFieldGroupHeader titleText={{ text: _("Automatic") }} |
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.
This should probably be called "Import"?
# increasing productivity | ||
keys_dir = "/etc/openvpn/server" | ||
m1.execute("touch .hushlogin") |
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 now? 😁
ea225de
to
f3eb448
Compare
✅ I've seen this flake https://cockpit-logs.us-east-1.linodeobjects.com/pull-19363-20231211-103844-f3eb448f-fedora-38-networking/log.html#40 couple times by now, but it doesn't happen locally. I'll dig into it. - Fixed now! ✅ Another flake is https://cockpit-logs.us-east-1.linodeobjects.com/pull-19363-20231212-130944-2f459d18-fedora-38-networking/log.html#40-2. When creating diffie-hellman params it times out sometimes, because it can take anywhere between less than a second to more than a minute. - Fixed! It generates a lot faster now with the ✅ Yet another flake is this one https://cockpit-logs.us-east-1.linodeobjects.com/pull-19363-20231212-115530-795d6a37-fedora-38-networking/log.html#40-1I'm debugging it at the moment. I reproduces fine in the CI (rarely locally). - Fixed! ❌ Huh another: https://cockpit-logs.us-east-1.linodeobjects.com/pull-19363-20231214-081835-ddd8075b-fedora-39-networking/log.html#41-1. There are many variations of it. It's a "heisenbug". Every time I add debug logs it vanishes 🤯 |
54629f4
to
cf54eac
Compare
58c0996
to
ddd8075
Compare
Well the most fundamentally weird thing is still that temporarily importing a connection with On Monday I found this KDE bug report and this commit closing it that uses a shared object exposed by NM. It's in C++, over the weekend I'll see if can do something similar in Python. |