launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #06910
[Merge] lp:~rvb/maas/maas-ssh-keys into lp:maas
Raphaël Badin has proposed merging lp:~rvb/maas/maas-ssh-keys into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~rvb/maas/maas-ssh-keys/+merge/99697
This branch adds a validator to src/maasserver/models.py:SSHKey.key to make sure that only valid public keys can be stored. It uses twisted.conch.ssh.keys to perform the actual key validation.
--
https://code.launchpad.net/~rvb/maas/maas-ssh-keys/+merge/99697
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/maas-ssh-keys into lp:maas.
=== modified file 'src/maasserver/models.py'
--- src/maasserver/models.py 2012-03-28 06:21:37 +0000
+++ src/maasserver/models.py 2012-03-28 10:48:00 +0000
@@ -40,6 +40,7 @@
from django.contrib import admin
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
+from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage
from django.db import models
@@ -62,6 +63,10 @@
POWER_TYPE,
POWER_TYPE_CHOICES,
)
+from twisted.conch.ssh.keys import (
+ BadKeyError,
+ Key,
+ )
# Special users internal to MAAS.
SYSTEM_USERS = [
@@ -683,6 +688,17 @@
return SSHKey.objects.filter(user=user).values_list('key', flat=True)
+def validate_ssh_public_key(value):
+ """Validate that the given value contains a valid SSH public key."""
+ try:
+ key = Key.fromString(value)
+ if not key.isPublic():
+ raise ValidationError(
+ "Invalid SSH public key (this key contains a private key).")
+ except BadKeyError:
+ raise ValidationError("Invalid SSH public key.")
+
+
class SSHKey(CommonInfo):
"""A `SSHKey` represents a user public SSH key.
@@ -698,7 +714,8 @@
user = models.ForeignKey(User, null=False, editable=False)
- key = models.TextField(null=False, editable=True)
+ key = models.TextField(
+ null=False, editable=True, validators=[validate_ssh_public_key])
def __unicode__(self):
return self.key
=== added directory 'src/maasserver/tests/data'
=== added file 'src/maasserver/tests/data/test_dsa'
--- src/maasserver/tests/data/test_dsa 1970-01-01 00:00:00 +0000
+++ src/maasserver/tests/data/test_dsa 2012-03-28 10:48:00 +0000
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQC5fDwjGkmt6QghiWia+JB9ED5a4Mhty5Gvv8uMcdXTriYabC3t
+lffgil+0s9cqYQrNuiqjBXv3m2BgFA4U3VZROP04KQD+Bok43TtRRl02HYEMiaX6
+edG01FtMyiD/3cB7OXQi5+F2AMV80rLzkRlUBmzOj+r4d5Ynk5HlRExmQwIVAIBo
+EpSY+9GojftVGPU8T0HaueR9AoGBAKVmDBdCFPgWFLRbsEUVBPcBBsQxI07bqFmA
+ljC+2Z/nBTryvgtMfGCLUN8SIiN2v9AwqAzyGT7yJlwzK7NM1Lp3oJ3UvYOydIAh
+xWPXXfq4GEoVB8AiPocvw/Q6dbpDZxg9G298ebxKEiusIayVgTOorO01uEeX78/8
+Q4a7SHMYAoGBAJbZsmuuWN2kb7lD27IzKcOgd07esoHPWZnv4qg7xhS1GdVr485v
+73OW1rfpWU6PdohckXLg9ZaoWtVTwNKTfHxS3iug9/pseBWTHdpmxCM5ClsZJii6
+T4frR5NTOCGKLxOamTs///OXopZr5u3vT20NFlzFE95J86tGtxYPPivxAhQByRHQ
+RXk6Jpjwa5kX+bYX1J3FIg==
+-----END DSA PRIVATE KEY-----
=== added file 'src/maasserver/tests/data/test_dsa.pub'
--- src/maasserver/tests/data/test_dsa.pub 1970-01-01 00:00:00 +0000
+++ src/maasserver/tests/data/test_dsa.pub 2012-03-28 10:48:00 +0000
@@ -0,0 +1,1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBALl8PCMaSa3pCCGJaJr4kH0QPlrgyG3Lka+/y4xx1dOuJhpsLe2V9+CKX7Sz1yphCs26KqMFe/ebYGAUDhTdVlE4/TgpAP4GiTjdO1FGXTYdgQyJpfp50bTUW0zKIP/dwHs5dCLn4XYAxXzSsvORGVQGbM6P6vh3lieTkeVETGZDAAAAFQCAaBKUmPvRqI37VRj1PE9B2rnkfQAAAIEApWYMF0IU+BYUtFuwRRUE9wEGxDEjTtuoWYCWML7Zn+cFOvK+C0x8YItQ3xIiI3a/0DCoDPIZPvImXDMrs0zUunegndS9g7J0gCHFY9dd+rgYShUHwCI+hy/D9Dp1ukNnGD0bb3x5vEoSK6whrJWBM6is7TW4R5fvz/xDhrtIcxgAAACBAJbZsmuuWN2kb7lD27IzKcOgd07esoHPWZnv4qg7xhS1GdVr485v73OW1rfpWU6PdohckXLg9ZaoWtVTwNKTfHxS3iug9/pseBWTHdpmxCM5ClsZJii6T4frR5NTOCGKLxOamTs///OXopZr5u3vT20NFlzFE95J86tGtxYPPivx ubuntu@server-7476
=== added file 'src/maasserver/tests/data/test_rsa'
--- src/maasserver/tests/data/test_rsa 1970-01-01 00:00:00 +0000
+++ src/maasserver/tests/data/test_rsa 2012-03-28 10:48:00 +0000
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA3a88w2TcMjFQbwU0+pAZ63z2b/wFG5MY+xuQmjE3cOsZCrYV
+dthJ7Q95cWkMUSs0E3wnNnfwgtSuLrIQnEbNUukkNsydow6tVJjlJAzILzYeCVYS
+WEinOprvIt7O6BkpgWnaOcL7ZaUszK7HDqX/EHv8Jk+Xx9digfYqSaqBTUDFW1XF
+WqxP7+sKZ9xmQutmEW+Yms/fzPrfdkIbudFtrvin6LqrSgdpcCAwymTMMN/BMbXT
+KLodhWacWqIeFHsuW0ad7TNyYJ1nF+n8lDqdoMSUTyJQ/a62YV+SJBJGTPDEG3T0
+0C4CH/fKBaYeURusNbdNgbyPZySjOypChHwR7QIDAQABAoIBAE5/DH8LqcTEHX0S
+VO4cNHFkMEb68DwRXBkea5eNsdn0BUv7qaIJeDPO9OupjMj5CVmU7rWkxq8s6/hw
+6NzNXUrsbvxQe8kPG2UHNqwLMp81BHG93oUQRNbFocOxLYaV0lKWzsUBO8+EK1bW
+1HllYenOXTybll0W8TSfm9212E8n5YFYoJDFH9nEDiUqDcYLOKJc5njceZUr0KQ2
+eKTpaNEtS78crNAwvdu4UzfC/I4ezfoWreXao0epr3anfTXXYf2TrdthgG7FclNP
+aOrCsQFXMrqVIc/FVXmbPKfhZOnOGglKVEUr0OmG3mfKan60636bGoiJJ2D6snKw
+YCAk8mkCgYEA8TcYZAG7gsi/1yTDrIfcrm5zGGBQ371vNOsTOVXGD28mepwUUl3B
+SucD7dAXlAyN/ikHly/wX/tVw3tF7N8nJx1wJ+KwGYgTVCgRBXexjiwz6NdyMbQX
+F7kb6LQjL6P40ygYTjVuFgee2KXd11NuT5pW1wleF3cY3tKWx0TWgEcCgYEA60Wv
+qz5yMg9+9A85Qis3VAw2DgJ3j12RYfSLhL0zkgZ6M1caZqMBuP7Q3HLlrEVJ+PJY
+aIiidIz9VLARa9wetAfJUVDsi/aijVXknLdm18Rujymsf97Wa4xj+006VmjdEeXV
+RoZGJ3l+j7yo2yfHxO1hHLLiXRXRQwOmUIGgSisCgYEAzYoI+o6PXS36ajUll0pd
+vTTYVhkcUMp2jD0TMHPqRRSNUUTV/Clvn4eiTW5X6QuZos0LbsSmquLbfar5NpIg
+JrBq9VGwhNDyx28sseAAKAl6YhnTcI7oboqJQYzdvqaWTDeKHnpgx9zOegU8N1Mc
+WDBHdwzAZHZTduszF7GMpdkCgYAQ7SuNS2nV1i2RC4NYElnhrxs4eM73PokWHgzn
+mOEb8WFbTjn1Bmc6UwLdyVpiwX1n7q+TnbjqX7ZeIGiwdN60nxbJxeOu0iixuGtB
+JyS8A0LdA+eIL5UHmcsbqlu3GcZF4l4su75SWrhTSQRw9/S0Y0uoT+pfPhGXG60c
+f6bzjwKBgQDe+l7pa+qkE0a8B11CgqKzmHOa/PRool7+0//WA5/H6jx0iAH5Ms2f
+8bpVbWugyXOFXkFN+DOfzJgar5EQmAtpipx6OKx1DXQqabmUlm75HOkr1dxOshou
+w39I3JOc1yHjlPJHjVyJqJcVOHYAFbEu5w+Sk0YELajvgU7FkfkonA==
+-----END RSA PRIVATE KEY-----
=== added file 'src/maasserver/tests/data/test_rsa.pub'
--- src/maasserver/tests/data/test_rsa.pub 1970-01-01 00:00:00 +0000
+++ src/maasserver/tests/data/test_rsa.pub 2012-03-28 10:48:00 +0000
@@ -0,0 +1,1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDdrzzDZNwyMVBvBTT6kBnrfPZv/AUbkxj7G5CaMTdw6xkKthV22EntD3lxaQxRKzQTfCc2d/CC1K4ushCcRs1S6SQ2zJ2jDq1UmOUkDMgvNh4JVhJYSKc6mu8i3s7oGSmBado5wvtlpSzMrscOpf8Qe/wmT5fH12KB9ipJqoFNQMVbVcVarE/v6wpn3GZC62YRb5iaz9/M+t92Qhu50W2u+KfouqtKB2lwIDDKZMww38ExtdMouh2FZpxaoh4Uey5bRp3tM3JgnWcX6fyUOp2gxJRPIlD9rrZhX5IkEkZM8MQbdPTQLgIf98oFph5RG6w1t02BvI9nJKM7KkKEfBHt ubuntu@server-7476
=== modified file 'src/maasserver/tests/test_models.py'
--- src/maasserver/tests/test_models.py 2012-03-27 10:40:40 +0000
+++ src/maasserver/tests/test_models.py 2012-03-28 10:48:00 +0000
@@ -40,6 +40,7 @@
SSHKey,
SYSTEM_USERS,
UserProfile,
+ validate_ssh_public_key,
)
from maasserver.provisioning import get_provisioning_api_proxy
from maasserver.testing.enum import map_enum
@@ -520,6 +521,44 @@
self.assertTrue(set(SYSTEM_USERS).isdisjoint(usernames))
+
+class SSHKeyValidatorTest(TestCase):
+
+ def get_data(self, filename):
+ """Utility method to read the content of files in
+ src/maasserver/tests.
+
+ Usually used to read files in src/maasserver/tests/data."""
+ path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), filename)
+ return file(path).read()
+
+ def test_validates_rsa_public_key(self):
+ key_string = self.get_data('data/test_rsa.pub')
+ validate_ssh_public_key(key_string)
+ # No ValidationError.
+
+ def test_validates_dsa_public_key(self):
+ key_string = self.get_data('data/test_dsa.pub')
+ validate_ssh_public_key(key_string)
+ # No ValidationError.
+
+ def test_does_not_validate_random_data(self):
+ key_string = factory.getRandomString()
+ self.assertRaises(
+ ValidationError, validate_ssh_public_key, key_string)
+
+ def test_does_not_validate_rsa_private_key(self):
+ key_string = self.get_data('data/test_rsa')
+ self.assertRaises(
+ ValidationError, validate_ssh_public_key, key_string)
+
+ def test_does_not_validate_dsa_private_key(self):
+ key_string = self.get_data('data/test_dsa')
+ self.assertRaises(
+ ValidationError, validate_ssh_public_key, key_string)
+
+
class SSHKeyManagerTest(TestCase):
"""Testing for the :class `SSHKeyManager` model manager."""
Follow ups