Skip to content

Commit

Permalink
Merge pull request #3009 from vyos/mergify/bp/sagitta/pr-2988
Browse files Browse the repository at this point in the history
rpki: T6034: move file based SSH keys for authentication to PKI subsystem (backport #2988)
  • Loading branch information
c-po committed Feb 14, 2024
2 parents 5d70d5e + 86612b1 commit 697ce8c
Show file tree
Hide file tree
Showing 11 changed files with 403 additions and 60 deletions.
1 change: 1 addition & 0 deletions data/config-mode-dependencies/vyos-1x.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"https": ["service_https"],
"ipsec": ["vpn_ipsec"],
"openconnect": ["vpn_openconnect"],
"rpki": ["protocols_rpki"],
"sstp": ["vpn_sstp"]
},
"vpn_l2tp": {
Expand Down
14 changes: 14 additions & 0 deletions interface-definitions/include/pki/openssh-key.xml.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- include start from pki/openssh-key.xml.i -->
<leafNode name="key">
<properties>
<help>OpenSSH key in PKI configuration</help>
<completionHelp>
<path>pki openssh</path>
</completionHelp>
<valueHelp>
<format>txt</format>
<description>Name of OpenSSH key in PKI configuration</description>
</valueHelp>
</properties>
</leafNode>
<!-- include end -->
39 changes: 39 additions & 0 deletions interface-definitions/pki.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,45 @@
</node>
</children>
</tagNode>
<tagNode name="openssh">
<properties>
<help>OpenSSH public and private keys</help>
</properties>
<children>
<node name="public">
<properties>
<help>Public key</help>
</properties>
<children>
#include <include/pki/cli-public-key-base64.xml.i>
<leafNode name="type">
<properties>
<help>SSH public key type</help>
<completionHelp>
<list>ssh-rsa</list>
</completionHelp>
<valueHelp>
<format>ssh-rsa</format>
<description>Key pair based on RSA algorithm</description>
</valueHelp>
<constraint>
<regex>(ssh-rsa)</regex>
</constraint>
</properties>
</leafNode>
</children>
</node>
<node name="private">
<properties>
<help>Private key</help>
</properties>
<children>
#include <include/pki/cli-private-key-base64.xml.i>
#include <include/pki/password-protected.xml.i>
</children>
</node>
</children>
</tagNode>
<tagNode name="openssh">
<properties>
<help>OpenSSH public and private keys</help>
Expand Down
17 changes: 1 addition & 16 deletions interface-definitions/protocols_rpki.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,7 @@
<help>RPKI SSH connection settings</help>
</properties>
<children>
<leafNode name="private-key-file">
<properties>
<help>RPKI SSH private key file</help>
<constraint>
<validator name="file-path"/>
</constraint>
</properties>
</leafNode>
<leafNode name="public-key-file">
<properties>
<help>RPKI SSH public key file path</help>
<constraint>
<validator name="file-path"/>
</constraint>
</properties>
</leafNode>
#include <include/pki/openssh-key.xml.i>
#include <include/generic-username.xml.i>
</children>
</node>
Expand Down
31 changes: 27 additions & 4 deletions python/vyos/pki.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
# Copyright (C) 2023 VyOS maintainers and contributors
# Copyright (C) 2023-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
Expand All @@ -20,7 +20,9 @@
from cryptography import x509
from cryptography.exceptions import InvalidSignature
from cryptography.x509.extensions import ExtensionNotFound
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID, ExtensionOID
from cryptography.x509.oid import NameOID
from cryptography.x509.oid import ExtendedKeyUsageOID
from cryptography.x509.oid import ExtensionOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import dh
Expand All @@ -45,6 +47,8 @@
DH_END='\n-----END DH PARAMETERS-----'
OVPN_BEGIN = '-----BEGIN OpenVPN Static key V{0}-----\n'
OVPN_END = '\n-----END OpenVPN Static key V{0}-----'
OPENSSH_KEY_BEGIN='-----BEGIN OPENSSH PRIVATE KEY-----\n'
OPENSSH_KEY_END='\n-----END OPENSSH PRIVATE KEY-----'

# Print functions

Expand Down Expand Up @@ -229,6 +233,12 @@ def wrap_public_key(raw_data):
def wrap_private_key(raw_data, passphrase=None):
return (KEY_ENC_BEGIN if passphrase else KEY_BEGIN) + raw_data + (KEY_ENC_END if passphrase else KEY_END)

def wrap_openssh_public_key(raw_data, type):
return f'{type} {raw_data}'

def wrap_openssh_private_key(raw_data):
return OPENSSH_KEY_BEGIN + raw_data + OPENSSH_KEY_END

def wrap_certificate_request(raw_data):
return CSR_BEGIN + raw_data + CSR_END

Expand All @@ -245,7 +255,6 @@ def wrap_openvpn_key(raw_data, version='1'):
return OVPN_BEGIN.format(version) + raw_data + OVPN_END.format(version)

# Load functions

def load_public_key(raw_data, wrap_tags=True):
if wrap_tags:
raw_data = wrap_public_key(raw_data)
Expand All @@ -267,6 +276,21 @@ def load_private_key(raw_data, passphrase=None, wrap_tags=True):
except ValueError:
return False

def load_openssh_public_key(raw_data, type):
try:
return serialization.load_ssh_public_key(bytes(f'{type} {raw_data}', 'utf-8'))
except ValueError:
return False

def load_openssh_private_key(raw_data, passphrase=None, wrap_tags=True):
if wrap_tags:
raw_data = wrap_openssh_private_key(raw_data)

try:
return serialization.load_ssh_private_key(bytes(raw_data, 'utf-8'), password=passphrase)
except ValueError:
return False

def load_certificate_request(raw_data, wrap_tags=True):
if wrap_tags:
raw_data = wrap_certificate_request(raw_data)
Expand Down Expand Up @@ -429,4 +453,3 @@ def ca_cmp(ca_name1, ca_name2, pki_node):

from functools import cmp_to_key
return sorted(ca_names, key=cmp_to_key(lambda cert1, cert2: ca_cmp(cert1, cert2, pki_node)))

41 changes: 40 additions & 1 deletion smoketest/bin/vyos-configtest-pki
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
# Copyright (C) 2022, VyOS maintainers and contributors
# Copyright (C) 2022-2024, VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
Expand All @@ -23,6 +23,7 @@ from vyos.pki import create_dh_parameters
from vyos.pki import encode_certificate
from vyos.pki import encode_dh_parameters
from vyos.pki import encode_private_key
from vyos.utils.file import write_file

subject = {'country': 'DE', 'state': 'BY', 'locality': 'Cloud', 'organization': 'VyOS', 'common_name': 'vyos'}
ca_subject = {'country': 'DE', 'state': 'BY', 'locality': 'Cloud', 'organization': 'VyOS', 'common_name': 'vyos CA'}
Expand All @@ -41,6 +42,40 @@ dh_pem = '/config/auth/ovpn_test_dh.pem'
s2s_key = '/config/auth/ovpn_test_site2site.key'
auth_key = '/config/auth/ovpn_test_tls_auth.key'

rpki_ssh_priv_key = """
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAweDyflDFR4qyEwETbJkZ2ZZc+sJNiDTvYpwGsWIkju49lJSxHe1x
Kf8FhwfyMu40Snt1yDlRmmmz4CsbLgbuZGMPvXG11e34+C0pSVUvpF6aqRTeLl1pDRK7Rn
jgm3su+I8SRLQR4qbLG6VXWOFuVpwiqbExLaU0hFYTPNP+dArNpsWEEKsohk6pTXdhg3Vz
Wp3vCMjl2JTshDa3lD7p2xISSAReEY0fnfEAmQzH4Z6DIwwGdFuMWoQIg+oFBM9ARrO2/F
IjRsz6AecR/WeU72JEw4aJic1/cAJQA6PiQBHwkuo3Wll1tbpxeRZoB2NQG22ETyJLvhfT
aooNLT9HpQAAA8joU5dM6FOXTAAAAAdzc2gtcnNhAAABAQDB4PJ+UMVHirITARNsmRnZll
z6wk2INO9inAaxYiSO7j2UlLEd7XEp/wWHB/Iy7jRKe3XIOVGaabPgKxsuBu5kYw+9cbXV
7fj4LSlJVS+kXpqpFN4uXWkNErtGeOCbey74jxJEtBHipssbpVdY4W5WnCKpsTEtpTSEVh
M80/50Cs2mxYQQqyiGTqlNd2GDdXNane8IyOXYlOyENreUPunbEhJIBF4RjR+d8QCZDMfh
noMjDAZ0W4xahAiD6gUEz0BGs7b8UiNGzPoB5xH9Z5TvYkTDhomJzX9wAlADo+JAEfCS6j
daWXW1unF5FmgHY1AbbYRPIku+F9Nqig0tP0elAAAAAwEAAQAAAQACkDlUjzfUhtJs6uY5
WNrdJB5NmHUS+HQzzxFNlhkapK6+wKqI1UNaRUtq6iF7J+gcFf7MK2nXS098BsXguWm8fQ
zPuemoDvHsQhiaJhyvpSqRUrvPTB/f8t/0AhQiKiJIWgfpTaIw53inAGwjujNNxNm2eafH
TThhCYxOkRT7rsT6bnSio6yeqPy5QHg7IKFztp5FXDUyiOS3aX3SvzQcDUkMXALdvzX50t
1XIk+X48Rgkq72dL4VpV2oMNDu3hM6FqBUplf9Mv3s51FNSma/cibCQoVufrIfoqYjkNTj
IpYFUcq4zZ0/KvgXgzSsy9VN/4TtbalrOuu7X/SHJbvhAAAAgGPFsXgONYQvXxCnK1dIue
ozgaZg1I/n522E2ZCOXBW4dYJVyNpppwRreDzuFzTDEe061MpNHfScjVBJCCulivFYWscL
6oaGsryDbFxO3QmB4I98UBqrds2yan9/JGc6EYe299yvaHy7Y64+NC0+fN8H2RAZ61T4w1
0JrCaJRyvzAAAAgQDvBfuV1U7o9k/fbU+U7W2UYnWblpOZAMfi1XQP6IJJeyWs90PdTdXh
+l0eIQrCawIiRJytNfxMmbD4huwTf77fWiyCcPznmALQ7ex/yJ+W5Z0V4dPGF3h7o1uiS2
36JhQ7mfcliCkhp/1PIklBIMPcCp0zl+s9wMv2hX7w1Pah9QAAAIEAz6YgU9Xute+J+dBw
oWxEQ+igR6KE55Um7O9AvSrqnCm9r7lSFsXC2ErYOxoDSJ3yIBEV0b4XAGn6tbbVIs3jS8
BnLHxclAHQecOx1PGn7PKbnPW0oJRq/X9QCIEelKYvlykpayn7uZooTXqcDaPZxfPpmPdy
e8chVJvdygi7kPEAAAAMY3BvQExSMS53dWUzAQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----
"""

rpki_ssh_pub_key = """
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDB4PJ+UMVHirITARNsmRnZllz6wk2INO9inAaxYiSO7j2UlLEd7XEp/wWHB/Iy7jRKe3XIOVGaabPgKxsuBu5kYw+9cbXV7fj4LSlJVS+kXpqpFN4uXWkNErtGeOCbey74jxJEtBHipssbpVdY4W5WnCKpsTEtpTSEVhM80/50Cs2mxYQQqyiGTqlNd2GDdXNane8IyOXYlOyENreUPunbEhJIBF4RjR+d8QCZDMfhnoMjDAZ0W4xahAiD6gUEz0BGs7b8UiNGzPoB5xH9Z5TvYkTDhomJzX9wAlADo+JAEfCS6jdaWXW1unF5FmgHY1AbbYRPIku+F9Nqig0tP0el vyos@vyos
"""

def create_cert(subject, cert_path, key_path, sign_by=None, sign_by_key=None, ca=False, sub_ca=False):
priv_key = create_private_key('rsa', 2048)
cert_req = create_certificate_request(subject, priv_key)
Expand Down Expand Up @@ -98,3 +133,7 @@ if __name__ == '__main__':

# OpenVPN Auth Key
system(f'openvpn --genkey secret {auth_key}')

write_file('/config/id_rsa', rpki_ssh_priv_key.strip())
write_file('/config/id_rsa.pub', rpki_ssh_pub_key.strip())
write_file('/config/known-hosts-file', '')
71 changes: 71 additions & 0 deletions smoketest/configs/rpki-only
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
interfaces {
ethernet eth0 {
duplex auto
speed auto
address 192.0.2.1/24
}
loopback lo {
}
}
protocols {
rpki {
cache 1.2.3.4 {
port 3323
preference 10
}
cache 5.6.7.8 {
port 2222
preference 20
ssh {
known-hosts-file "/config/known-hosts-file"
private-key-file "/config/id_rsa"
public-key-file "/config/id_rsa.pub"
username vyos
}
}
}
}
system {
config-management {
commit-revisions 200
}
console {
device ttyS0 {
speed 115200
}
}
conntrack {
modules {
ftp
h323
nfs
pptp
sip
sqlnet
tftp
}
}
host-name vyos
login {
user vyos {
authentication {
encrypted-password $6$r/Yw/07NXNY$/ZB.Rjf9jxEV.BYoDyLdH.kH14rU52pOBtrX.4S34qlPt77chflCHvpTCq9a6huLzwaMR50rEICzA5GoIRZlM0
plaintext-password ""
}
}
}
syslog {
global {
facility all {
level debug
}
facility protocols {
level debug
}
}
}
}

// Warning: Do not remove the following line.
// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:container@1:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
// Release version: 1.3.5

0 comments on commit 697ce8c

Please sign in to comment.