469 lines
28 KiB
Python
469 lines
28 KiB
Python
import json
|
|
from calendar import timegm
|
|
from datetime import datetime, UTC, timedelta
|
|
from textwrap import wrap
|
|
from cryptography import x509
|
|
from cryptography.hazmat._oid import NameOID
|
|
from cryptography.hazmat.primitives import serialization, hashes
|
|
from cryptography.hazmat.primitives.asymmetric.rsa import generate_private_key
|
|
from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key, Encoding
|
|
from dateutil.relativedelta import relativedelta
|
|
from jose import jwk, jws
|
|
from jose.constants import ALGORITHMS
|
|
|
|
"""
|
|
Any variables prefixed with `NV_` or `nv_` are original values, dumped from an NLS registration/activation process.
|
|
Any variables prefixed with `MY_` or `my_` are variables which are set by fastapi-dls and are "faked".
|
|
"""
|
|
|
|
### DEFAULTS
|
|
|
|
# SELECT xid FROM request_routing.service_instance
|
|
NV_SI_SITE_ID = '4e53a171-103b-4946-9ed8-5f4c0ee750d9'
|
|
# SELECT value FROM si_<xid>.service_instance_artifact WHERE namespace = 'service_instance.client.all' and name = 'private_key'
|
|
NV_SI_KEY_RSA = """-----BEGIN RSA PRIVATE KEY-----
|
|
MIIEpAIBAAKCAQEAyIz6i48cFn4XOK0S2GTYpLMU85xzJ1fmQmA2nC6Zod2V4BxN
|
|
Xqk+9y8nvdzZVELxmC+N47ZQGV/J5cquIadx0V42F3JTryJFDuZ+7fQsNlXUX3og
|
|
UQhhgvHuluhDJQSvdZAzpguS7N+gJGCGbGk1pZBYL2JtTDTWSIcWsQtD/w9DAPEk
|
|
K5cHGoZkovngH1LOTkVAcyEqKxLblerMnLu3rOaDVkEcf+1l2BwvHUWTU4LI6uud
|
|
CWP2em69T2EXp1qczi5IKJzc53puNfp5nXlHayrneYAdIbEAQSQg+Z40npUwNKW7
|
|
1Ue2NsG3SoGWuj3lTyEVXlLsAw0bsCDVLipMWwIDAQABAoIBAA24FyuU221ueSHK
|
|
m49ro3Mg2dep/10ICYH6f8HcLjmBPwKlucucwehTtK3esPJ8SEQ9r8DA2zN6w56R
|
|
aHgRsrRWQL0Gq4YMTuascRWce0NirueyvKM02SoFnGl8wGfrE7wNfhSalhWkkDMg
|
|
DaujRtg2MTiMmY15z9U5gh16XjYEZipOmfmNWHLCMRnEsXV/ToZ+g7ekruKPweGD
|
|
A52tG0pN/KYVaQFX+sZ7eXpd1jEl4gCSHup1SopAM3+is0DzeHiLSg9ZUN9dd8af
|
|
L+SYAOCjRHXkUKcQN8a3FffoPInjy4D57dndkqRusiCtRJV3TEjO4Ld9cj/fqQZ2
|
|
kDMT0YECgYEA0iPJu73Kz3wruxGfzq2zTE8RMM/EF8OAXi/qzKer40w7KLZ4aY0c
|
|
5FUJwehipYM390/OUf0x3jiwMVk3wR6M9/L9h70zN1OCIKnCbLc+e0sgK9nYY98y
|
|
XxXIu/HfRi42usAg6IQsr41z+Y7qY/zlyIDdoGJPTgra2aFUbYG/pD8CgYEA9FF2
|
|
GfBlC5NUxwjjwEeNXvKU3wvzoZ0wS3EMrj0ylXY/4Q+thlfOWiGBKUOik8mSohgL
|
|
9qP756185Map/szCUzjlr13hgLg+nECJuP6hLWP2V4O+vS2dNg+lxWJ7EZVxhRR1
|
|
ueJE4xkOU2v00b0H+nJyDnoEhdHlvFFVnh+roOUCgYEAnyxwoH8Q4r1hup+M91bn
|
|
m4PAt8KI/J8f2zhcmIzhTJjvrtUYvIshOWuYqoLGRizw9apD1CL/5R33iEnWS7hC
|
|
e4ZZuLn904iz5t3v4b2j3Gx5f/3RRUVJuHCdzo9V2qki1660vqtv1cJF+ODidr6X
|
|
p5rFRblx7OGYCIWFmDVR3q0CgYBZZ03eZBe1yq4lP12ISSa0bfSIQmle5JR9ptrL
|
|
D93oz6LEiuYm2Q7L8KLBJNzjU8nywvXtxUgzGUswtHoUoX0i0xlJuQMCBWnz57H+
|
|
Hj+AyqmkkLNFquFynPs+ZbE/V/54gmoqIWCv8cVKRaEK9y9qOGMAZSouhgaZiPHZ
|
|
sSEu+QKBgQDRpPzQrn0xD0QPvQMi/gl8TJHjEfjQkGkxREa1XAKj4XcHXKwzSfdf
|
|
LdUhyKEt/if0EJd09UbH6+T7aqkuw4HthF8ab2FSlLcyQ6t0UYUlTwCLTHsquqeu
|
|
5+Le7DO89hskB8DKr4Oobmr12eulCf81UDYWSKhDYeqrBJyf3PopLg==
|
|
-----END RSA PRIVATE KEY-----
|
|
"""
|
|
# SELECT value FROM service_instance_artifact WHERE namespace = 'service_instance.client.all' and name = 'public_key'
|
|
NV_SI_KEY_PUB = """-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyIz6i48cFn4XOK0S2GTY
|
|
pLMU85xzJ1fmQmA2nC6Zod2V4BxNXqk+9y8nvdzZVELxmC+N47ZQGV/J5cquIadx
|
|
0V42F3JTryJFDuZ+7fQsNlXUX3ogUQhhgvHuluhDJQSvdZAzpguS7N+gJGCGbGk1
|
|
pZBYL2JtTDTWSIcWsQtD/w9DAPEkK5cHGoZkovngH1LOTkVAcyEqKxLblerMnLu3
|
|
rOaDVkEcf+1l2BwvHUWTU4LI6uudCWP2em69T2EXp1qczi5IKJzc53puNfp5nXlH
|
|
ayrneYAdIbEAQSQg+Z40npUwNKW71Ue2NsG3SoGWuj3lTyEVXlLsAw0bsCDVLipM
|
|
WwIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
"""
|
|
MY_CLIENT_TOKEN_EXPIRE_DELTA = relativedelta(years=12)
|
|
|
|
NV_CONFIG_TOKEN_RESPONSE = {
|
|
"certificateConfiguration": {
|
|
"caChain": [
|
|
"-----BEGIN CERTIFICATE-----\r\n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\r\n56OFWPHcA7gxkpU8wftrVMLFeDvLIGc=\r\n-----END CERTIFICATE-----"
|
|
],
|
|
"publicCert": "-----BEGIN CERTIFICATE-----\r\nMIIE2zCCAsOgAwIBAgIUU1iWuS2t3ufw2dvXTEC0VmhpY4IwDQYJKoZIhvcNAQELBQAwejELMAkG\r\nA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNVBAoTBk52aWRpYTEnMCUGA1UECxMe\r\nTnZpZGlhIExpY2Vuc2luZyBTZXJ2aWNlIChOTFMpMRwwGgYDVQQDExNOTFMgSW50ZXJtZWRpYXRl\r\nIENBMB4XDTI1MDMxMjEyMjY1MVoXDTI4MDMxMTEyMjcyMVowLzEtMCsGA1UEAxMkNGU1M2ExNzEt\r\nMTAzYi00OTQ2LTllZDgtNWY0YzBlZTc1MGQ5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\r\nAQEAsFLwIgL4xu4BAGiQSUeb66F87tZBKn057uK92QPbPMxRFCD9gN0NUxv5apEDxWLaUecugvOb\r\np3d1hCrkUkXdu7Ogb2GZMQXqCvBFvZX7S2ZFEA9XhV2hLzHYMVLz3dsVnZP/R4+rF3qPYx4rlkJq\r\n+XWr/y6kO93ocoqFkIQF0QfZ+tD6ydyfZdSAShjnOVlzds2fmaFHJJGLo/SsvjcnuVpJ+qKaoyD+\r\ndOvTVaYCrCNcI2cJ6sgSPp1xWrt9Hu21lr0tH5nou4dwWPdlciF6IfrnmHHdbwOlbCz4TS/t4hpB\r\nFD/bDNNVUobu+KRHJRGXKlrBk+Udx0dpmkUZ80WOFQIDAQABo4GjMIGgMA4GA1UdDwEB/wQEAwID\r\nqDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFJ/o520oGIqKTmima73E\r\n9NgNbIk2MB8GA1UdIwQYMBaAFEo1JPxQ95lhCAtksQowEaSVoAMeMC8GA1UdEQQoMCaCJDRlNTNh\r\nMTcxLTEwM2ItNDk0Ni05ZWQ4LTVmNGMwZWU3NTBkOTANBgkqhkiG9w0BAQsFAAOCAgEAv9NcfpBU\r\nxZP9PsdJ4twWu/EQqeJRsrTV3ngg6o9JV22285p5TbhTk9aKa6HlME9KoYDlXo1yn4pwVL6TFc/W\r\nR+2UJJphrlZGEUJvTrEwDxs29QXjkWAJ+2KZoLHdKK1luV1QAV2x8/hTWUvj4pnpRUHvdXAWu3uy\r\nVUYhE2Ypj6Lq6ipzHQCh+ZM6Zyml6Em/byRrIv6dv/DH7QsQCqXmuyxajTNYmexG33HOr5R/JAX/\r\n4xC1C9KB0Ru1NcJRIKJ+OPiXEJNXugvAMx02MJw5fETEEvGY8YakjaRFn9p7cfRCBFbJWWyQ2RM8\r\n8Z9pr2JrDzDIImBZ5LY4KpvYhsWr2R2mYqtNw0P3FPfm23x0WzSx10TtRnEX1I1349CDwNIOFpQr\r\ncW3mBtX0pb/iOwazvBfxCO7Y7FrHXVxv0tPtJg6PSdCyp7Lgu2zIsWuteHOnaoo+IXocAbSuTmIN\r\n0yduLkYU0XBJOouO0fBziorL6S7ifeaVP/ppRnF0L61DLbaHy8qkqBQTe9JQRHmV+owl0lsHrYRI\r\nRKOxVxFS2UmAJZiqnJ/HI2nHRqZerH5c465u8N3xuT71HxsoFxiu4tQM0NEGGUoooefX/ramo4P+\r\neEVOavIG7uVFzYnrfadEZiCF+hLQf/DNgueHglgaibGAbSTILhVaQ+9KvlhMh5Am2tU=\r\n-----END CERTIFICATE-----",
|
|
"publicKey": {
|
|
"exp": 65537,
|
|
"mod": [
|
|
"b052f02202f8c6ee0100689049479beba17ceed6412a7d39eee2bdd903db3ccc511420fd80dd0d531bf96a9103c562da51e72e82f39ba77775842ae45245ddbbb3a06f61993105ea0af045bd95fb4b6645100f57855da12f31d83152f3dddb159d93ff478fab177a8f631e2b96426af975abff2ea43bdde8728a85908405d107d9fad0fac9dc9f65d4804a18e739597376cd9f99a14724918ba3f4acbe3727b95a49faa29aa320fe74ebd355a602ac235c236709eac8123e9d715abb7d1eedb596bd2d1f99e8bb877058f76572217a21fae79871dd6f03a56c2cf84d2fede21a41143fdb0cd3555286eef8a4472511972a5ac193e51dc747699a4519f3458e15"
|
|
]
|
|
}
|
|
},
|
|
"configToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJOTFMgU2VydmljZSBJbnN0YW5jZSIsImF1ZCI6Ik5MUyBMaWNlbnNlZCBDbGllbnQiLCJpYXQiOjE3NDIxOTU4ODUsIm5iZiI6MTc0MjE5NTg4NSwiZXhwIjoxNzQyMTk2Nzg1LCJwcm90b2NvbF92ZXJzaW9uIjoiMi4wIiwiZF9uYW1lIjoiRExTIiwic2VydmljZV9pbnN0YW5jZV9yZWYiOiI0ZTUzYTE3MS0xMDNiLTQ5NDYtOWVkOC01ZjRjMGVlNzUwZDkiLCJzZXJ2aWNlX2luc3RhbmNlX3B1YmxpY19rZXlfY29uZmlndXJhdGlvbiI6eyJzZXJ2aWNlX2luc3RhbmNlX3B1YmxpY19rZXlfbWUiOnsibW9kIjoiYzg4Y2ZhOGI4ZjFjMTY3ZTE3MzhhZDEyZDg2NGQ4YTRiMzE0ZjM5YzczMjc1N2U2NDI2MDM2OWMyZTk5YTFkZDk1ZTAxYzRkNWVhOTNlZjcyZjI3YmRkY2Q5NTQ0MmYxOTgyZjhkZTNiNjUwMTk1ZmM5ZTVjYWFlMjFhNzcxZDE1ZTM2MTc3MjUzYWYyMjQ1MGVlNjdlZWRmNDJjMzY1NWQ0NWY3YTIwNTEwODYxODJmMWVlOTZlODQzMjUwNGFmNzU5MDMzYTYwYjkyZWNkZmEwMjQ2MDg2NmM2OTM1YTU5MDU4MmY2MjZkNGMzNGQ2NDg4NzE2YjEwYjQzZmYwZjQzMDBmMTI0MmI5NzA3MWE4NjY0YTJmOWUwMWY1MmNlNGU0NTQwNzMyMTJhMmIxMmRiOTVlYWNjOWNiYmI3YWNlNjgzNTY0MTFjN2ZlZDY1ZDgxYzJmMWQ0NTkzNTM4MmM4ZWFlYjlkMDk2M2Y2N2E2ZWJkNGY2MTE3YTc1YTljY2UyZTQ4Mjg5Y2RjZTc3YTZlMzVmYTc5OWQ3OTQ3NmIyYWU3Nzk4MDFkMjFiMTAwNDEyNDIwZjk5ZTM0OWU5NTMwMzRhNWJiZDU0N2I2MzZjMWI3NGE4MTk2YmEzZGU1NGYyMTE1NWU1MmVjMDMwZDFiYjAyMGQ1MmUyYTRjNWIiLCJleHAiOjY1NTM3fSwic2VydmljZV9pbnN0YW5jZV9wdWJsaWNfa2V5X3BlbSI6Ii0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXlJejZpNDhjRm40WE9LMFMyR1RZXG5wTE1VODV4ekoxZm1RbUEybkM2Wm9kMlY0QnhOWHFrKzl5OG52ZHpaVkVMeG1DK040N1pRR1YvSjVjcXVJYWR4XG4wVjQyRjNKVHJ5SkZEdVorN2ZRc05sWFVYM29nVVFoaGd2SHVsdWhESlFTdmRaQXpwZ3VTN04rZ0pHQ0diR2sxXG5wWkJZTDJKdFREVFdTSWNXc1F0RC93OURBUEVrSzVjSEdvWmtvdm5nSDFMT1RrVkFjeUVxS3hMYmxlck1uTHUzXG5yT2FEVmtFY2YrMWwyQnd2SFVXVFU0TEk2dXVkQ1dQMmVtNjlUMkVYcDFxY3ppNUlLSnpjNTNwdU5mcDVuWGxIXG5heXJuZVlBZEliRUFRU1FnK1o0MG5wVXdOS1c3MVVlMk5zRzNTb0dXdWozbFR5RVZYbExzQXcwYnNDRFZMaXBNXG5Xd0lEQVFBQlxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tIiwia2V5X3JldGVudGlvbl9tb2RlIjoiTEFURVNUX09OTFkifX0.mZnB0NnE4WIxg0Q6zH98NSt6UYLbtbNPfWsVVJwtcn8rv9mFWmBr3vxB9BGzafY-kLo5uJztI_Ue3Q1VD5yHaMVtgrtI8K5-Ojm3d8p5hGe2qwoskQ1OXSSTE15JaGsdkTihPnZ-0r6RBRucXa-PoNWBYnvl0SbcNiU_-FAK1ugmemLW3Q9T2KZ71n8nr0-FXrJUpsxrluUEerhtDlOZmNHuCEcsU10U0ZdMPBc3iguy_psd_jR4QIDRwc6W0dp29403epDJqqkUW8c-ORi1Ny2Bk2OFNK87VBxf5GP5KxuYxlujtzf0Y1niDqnYdW1MpKl9OxRvz0E4HUEK7_JBbA"
|
|
}
|
|
|
|
### VARIABLES
|
|
|
|
nv_si_private_key = load_pem_private_key(NV_SI_KEY_RSA.encode('utf-8'), password=None)
|
|
nv_si_private_key_pem = nv_si_private_key.private_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
|
encryption_algorithm=serialization.NoEncryption()
|
|
)
|
|
nv_si_public_key = load_pem_public_key(NV_SI_KEY_PUB.encode('utf-8'))
|
|
nv_si_public_key_pem = nv_si_public_key.public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
)
|
|
nv_si_public_key_exp = nv_si_public_key.public_numbers().e
|
|
nv_si_public_key_mod = f'{nv_si_public_key.public_numbers().n:x}' # hex value without "0x" prefix
|
|
|
|
|
|
### TESTS
|
|
|
|
def test_private_public_key_equals_public_key():
|
|
"""
|
|
test that the public-key exported from private-key is the same as the defined public-key
|
|
|
|
:return:
|
|
"""
|
|
|
|
nv_public_key_from_private_key_as_pem = nv_si_private_key.public_key().public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
)
|
|
nv_public_key_as_pem = nv_si_public_key.public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
)
|
|
assert nv_public_key_as_pem == nv_public_key_from_private_key_as_pem
|
|
|
|
|
|
def test_official_cert():
|
|
"""
|
|
test the right certificate
|
|
|
|
:return:
|
|
"""
|
|
|
|
nv_response_certificate_configuration = NV_CONFIG_TOKEN_RESPONSE.get('certificateConfiguration')
|
|
nv_response_ca_cert = nv_response_certificate_configuration.get('caChain')[0].encode('utf-8')
|
|
nv_response_public_cert = nv_response_certificate_configuration.get('publicCert').encode('utf-8')
|
|
nv_response_public_key = nv_response_certificate_configuration.get('publicKey')
|
|
|
|
nv_response_parsed_ca_cert = x509.load_pem_x509_certificate(nv_response_ca_cert)
|
|
nv_response_parsed_cert = x509.load_pem_x509_certificate(nv_response_public_cert)
|
|
|
|
assert 4096 == nv_response_parsed_ca_cert.public_key().key_size
|
|
assert 2048 == nv_response_parsed_cert.public_key().key_size
|
|
#assert nv_response_parsed_cert.public_key().public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) == nv_si_public_key.public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo)
|
|
|
|
nv_response_parsed_cert_exp = nv_response_parsed_cert.public_key().public_numbers().e
|
|
nv_response_parsed_cert_mod = f'{nv_response_parsed_cert.public_key().public_numbers().n:x}' # hex value without "0x" prefix
|
|
assert nv_response_parsed_cert_exp == nv_response_public_key.get('exp')
|
|
assert nv_response_parsed_cert_mod == nv_response_public_key.get('mod')[0]
|
|
|
|
nv_issuer = f'CN=NLS Intermediate CA,OU=Nvidia Licensing Service (NLS),O=Nvidia,ST=California,C=US'
|
|
nv_subject = f'CN={NV_SI_SITE_ID}'
|
|
assert nv_response_parsed_cert.issuer.rfc4514_string() == nv_issuer
|
|
assert nv_response_parsed_cert.subject.rfc4514_string() == nv_subject
|
|
|
|
nv_ca_ski = nv_response_parsed_ca_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
|
nv_cert_aki = nv_response_parsed_cert.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier).value
|
|
assert nv_ca_ski.key_identifier == nv_cert_aki.key_identifier
|
|
|
|
|
|
def test_official_config_token_response():
|
|
"""
|
|
test config-token response and test jwt-signing
|
|
|
|
:return:
|
|
"""
|
|
|
|
nv_response_certificate_configuration = NV_CONFIG_TOKEN_RESPONSE.get('certificateConfiguration')
|
|
nv_response_public_cert = nv_response_certificate_configuration.get('publicCert').encode('utf-8')
|
|
nv_jwt_decode_key = jwk.construct(nv_response_public_cert, algorithm=ALGORITHMS.RS256)
|
|
|
|
nv_response_config_token = NV_CONFIG_TOKEN_RESPONSE.get('configToken')
|
|
|
|
payload = jws.verify(nv_response_config_token, key=nv_jwt_decode_key, algorithms=ALGORITHMS.RS256)
|
|
payload = json.loads(payload)
|
|
assert payload.get('iss') == 'NLS Service Instance'
|
|
assert payload.get('aud') == 'NLS Licensed Client'
|
|
assert payload.get('service_instance_ref') == NV_SI_SITE_ID
|
|
|
|
nv_si_public_key_configuration = payload.get('service_instance_public_key_configuration')
|
|
nv_si_public_key_me = nv_si_public_key_configuration.get('service_instance_public_key_me')
|
|
assert nv_si_public_key_me.get('mod') == nv_si_public_key_mod
|
|
assert nv_si_public_key_me.get('exp') == nv_si_public_key_exp
|
|
|
|
|
|
def test_our_config_token():
|
|
"""
|
|
test our config-token with nvidia data and test jwt-signing.
|
|
|
|
THIS TEST WILL FAIL UNTIL WE HAVE FOUND THE CORRECT PRIVATE KEY
|
|
|
|
:return:
|
|
"""
|
|
|
|
nv_response_certificate_configuration = NV_CONFIG_TOKEN_RESPONSE.get('certificateConfiguration')
|
|
nv_response_public_cert = nv_response_certificate_configuration.get('publicCert').encode('utf-8')
|
|
nv_response_parsed_cert = x509.load_pem_x509_certificate(nv_response_public_cert)
|
|
|
|
nv_response_parsed_cert_as_pem = nv_response_parsed_cert.public_bytes(encoding=Encoding.PEM)
|
|
jwt_decode_key = jwk.construct(nv_response_parsed_cert_as_pem, algorithm=ALGORITHMS.RS256)
|
|
|
|
### build payload
|
|
|
|
cur_time = datetime.now(UTC)
|
|
exp_time = cur_time + MY_CLIENT_TOKEN_EXPIRE_DELTA
|
|
|
|
my_payload = {
|
|
"iss": "NLS Service Instance",
|
|
"aud": "NLS Licensed Client",
|
|
"iat": timegm(cur_time.timetuple()),
|
|
"nbf": timegm(cur_time.timetuple()),
|
|
"exp": timegm(exp_time.timetuple()),
|
|
"protocol_version": "2.0",
|
|
"d_name": "DLS",
|
|
"service_instance_ref": NV_SI_SITE_ID,
|
|
"service_instance_public_key_configuration": {
|
|
"service_instance_public_key_me": {
|
|
"mod": hex(nv_si_public_key.public_numbers().n)[2:],
|
|
"exp": int(nv_si_public_key.public_numbers().e),
|
|
},
|
|
"service_instance_public_key_pem": nv_si_public_key_pem.decode('utf-8'),
|
|
"key_retention_mode": "LATEST_ONLY"
|
|
},
|
|
}
|
|
|
|
# todo: maybe DLS_SI_CERTIFICATE['private_key']
|
|
# our_correct_sign_key = load_key('our_correct_private_key.pem').export_key().decode('utf-8')
|
|
# our_correct_sign_key = jwk.construct(our_correct_sign_key, algorithm=ALGORITHMS.RS256)
|
|
nv_sign_key = jwk.construct(nv_si_private_key_pem.decode('utf-8'), algorithm=ALGORITHMS.RS256)
|
|
|
|
# our_correct_config_token = jws.sign(payload, key=our_correct_sign_key, headers=None, algorithm=ALGORITHMS.RS256)
|
|
# until we have not found the correct private key,
|
|
# "jwt_encode_key" has invalid signature (can't be verified with DLS_SI_CERTIFICATE['certificate'])
|
|
my_config_token = jws.sign(my_payload, key=nv_sign_key, headers=None, algorithm=ALGORITHMS.RS256)
|
|
|
|
my_response = {
|
|
"certificateConfiguration": {
|
|
"caChain": NV_CONFIG_TOKEN_RESPONSE['certificateConfiguration']['caChain'],
|
|
"publicCert": NV_CONFIG_TOKEN_RESPONSE['certificateConfiguration']['publicCert'],
|
|
"publicKey": {
|
|
"exp": int(nv_response_parsed_cert.public_key().public_numbers().e),
|
|
"mod": [hex(nv_response_parsed_cert.public_key().public_numbers().n)[2:]],
|
|
},
|
|
},
|
|
"configToken": my_config_token,
|
|
}
|
|
|
|
###
|
|
|
|
my_config_token = my_response.get('configToken')
|
|
|
|
# todo: this "jws.verify" will fail, because we *sign* with "nv_si_private_key_pem" but *verify* with
|
|
# the certificate (which dont belong together)
|
|
payload = jws.verify(my_config_token, key=jwt_decode_key, algorithms=ALGORITHMS.RS256)
|
|
payload = json.loads(payload)
|
|
assert payload.get('iss') == 'NLS Service Instance'
|
|
assert payload.get('aud') == 'NLS Licensed Client'
|
|
assert payload.get('service_instance_ref') == NV_SI_SITE_ID
|
|
|
|
service_si_public_key_configuration = payload.get('service_instance_public_key_configuration')
|
|
service_si_public_key_me = service_si_public_key_configuration.get('service_instance_public_key_me')
|
|
assert service_si_public_key_me.get('mod') == nv_si_public_key_mod
|
|
assert service_si_public_key_me.get('exp') == nv_si_public_key_exp
|
|
|
|
|
|
def test_our_config_token_with_our_key():
|
|
"""
|
|
test our config-token and test jwt-signing
|
|
|
|
:return:
|
|
"""
|
|
|
|
""" Create Root Key and Certificate """
|
|
|
|
# create root keypair
|
|
my_root_private_key = generate_private_key(public_exponent=65537, key_size=4096)
|
|
my_root_public_key = my_root_private_key.public_key()
|
|
|
|
# create root-certificate subject
|
|
my_root_subject = x509.Name([
|
|
x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
|
|
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'California'),
|
|
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Nvidia'),
|
|
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'Nvidia Licensing Service (NLS)'),
|
|
x509.NameAttribute(NameOID.COMMON_NAME, u'NLS Root CA'),
|
|
])
|
|
|
|
# create self-signed root-certificate
|
|
my_root_certificate = (
|
|
x509.CertificateBuilder()
|
|
.subject_name(my_root_subject)
|
|
.issuer_name(my_root_subject)
|
|
.public_key(my_root_public_key)
|
|
.serial_number(x509.random_serial_number())
|
|
.not_valid_before(datetime.now(tz=UTC) - timedelta(days=1))
|
|
.not_valid_after(datetime.now(tz=UTC) + timedelta(days=365 * 10))
|
|
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
|
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(my_root_public_key), critical=False)
|
|
.sign(my_root_private_key, hashes.SHA256()))
|
|
|
|
""" Create CA (Intermediate) Key and Certificate """
|
|
|
|
# create ca keypair
|
|
my_ca_private_key = generate_private_key(public_exponent=65537, key_size=4096)
|
|
my_ca_public_key = my_ca_private_key.public_key()
|
|
|
|
# create ca-certificate subject
|
|
my_ca_subject = x509.Name([
|
|
x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
|
|
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'California'),
|
|
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Nvidia'),
|
|
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'Nvidia Licensing Service (NLS)'),
|
|
x509.NameAttribute(NameOID.COMMON_NAME, u'NLS Intermediate CA'),
|
|
])
|
|
|
|
# create self-signed ca-certificate
|
|
my_ca_certificate = (
|
|
x509.CertificateBuilder()
|
|
.subject_name(my_ca_subject)
|
|
.issuer_name(my_root_subject)
|
|
.public_key(my_ca_public_key)
|
|
.serial_number(x509.random_serial_number())
|
|
.not_valid_before(datetime.now(tz=UTC) - timedelta(days=1))
|
|
.not_valid_after(datetime.now(tz=UTC) + timedelta(days=365 * 10))
|
|
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
|
|
.add_extension(x509.KeyUsage(digital_signature=False, key_encipherment=False, key_cert_sign=True,
|
|
key_agreement=False, content_commitment=False, data_encipherment=False,
|
|
crl_sign=True, encipher_only=False, decipher_only=False), critical=True)
|
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(my_ca_public_key), critical=False)
|
|
# .add_extension(x509.AuthorityKeyIdentifier.from_issuer_public_key(my_root_public_key), critical=False)
|
|
.add_extension(x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
|
my_root_certificate.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
|
), critical=False)
|
|
.sign(my_root_private_key, hashes.SHA256()))
|
|
|
|
with open('caChain_my.pem', 'wb') as f:
|
|
f.write(my_ca_certificate.public_bytes(encoding=Encoding.PEM))
|
|
|
|
""" Create Service-Instance Key and Certificate """
|
|
|
|
# create si keypair
|
|
my_si_private_key = generate_private_key(public_exponent=65537, key_size=2048)
|
|
my_si_public_key = my_si_private_key.public_key()
|
|
|
|
my_si_private_key_as_pem = my_si_private_key.private_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
|
encryption_algorithm=serialization.NoEncryption(),
|
|
)
|
|
my_si_public_key_as_pem = my_si_public_key.public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
)
|
|
|
|
with open('instance.private.pem', 'wb') as f:
|
|
f.write(my_si_private_key_as_pem)
|
|
|
|
with open('instance.public.pem', 'wb') as f:
|
|
f.write(my_si_public_key_as_pem)
|
|
|
|
# create si-certificate subject
|
|
my_si_subject = x509.Name([
|
|
x509.NameAttribute(NameOID.COMMON_NAME, u'4e53a171-103b-4946-9ed8-5f4c0ee750d9'),
|
|
])
|
|
|
|
# create self-signed si-certificate
|
|
my_si_certificate = (
|
|
x509.CertificateBuilder()
|
|
.subject_name(my_si_subject)
|
|
.issuer_name(my_ca_subject)
|
|
.public_key(my_si_public_key)
|
|
.serial_number(x509.random_serial_number())
|
|
.not_valid_before(datetime.now(tz=UTC) - timedelta(days=1))
|
|
.not_valid_after(datetime.now(tz=UTC) + timedelta(days=365 * 10))
|
|
.add_extension(x509.KeyUsage(digital_signature=True, key_encipherment=True, key_cert_sign=False,
|
|
key_agreement=True, content_commitment=False, data_encipherment=False,
|
|
crl_sign=False, encipher_only=False, decipher_only=False), critical=True)
|
|
.add_extension(x509.ExtendedKeyUsage([
|
|
x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
|
|
x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH]
|
|
), critical=False)
|
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(my_si_public_key), critical=False)
|
|
# .add_extension(x509.AuthorityKeyIdentifier.from_issuer_public_key(my_ca_public_key), critical=False)
|
|
.add_extension(x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
|
my_ca_certificate.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
|
), critical=False)
|
|
.add_extension(x509.SubjectAlternativeName([
|
|
x509.DNSName('4e53a171-103b-4946-9ed8-5f4c0ee750d9')
|
|
]), critical=False)
|
|
.sign(my_ca_private_key, hashes.SHA256()))
|
|
|
|
my_si_public_key_exp = my_si_certificate.public_key().public_numbers().e
|
|
my_si_public_key_mod = f'{my_si_certificate.public_key().public_numbers().n:x}' # hex value without "0x" prefix
|
|
|
|
with open('cert_my.pem', 'wb') as f:
|
|
f.write(my_si_certificate.public_bytes(encoding=Encoding.PEM))
|
|
|
|
""" build out payload """
|
|
|
|
cur_time = datetime.now(UTC)
|
|
exp_time = cur_time + MY_CLIENT_TOKEN_EXPIRE_DELTA
|
|
|
|
payload = {
|
|
"iss": "NLS Service Instance",
|
|
"aud": "NLS Licensed Client",
|
|
"iat": timegm(cur_time.timetuple()),
|
|
"nbf": timegm(cur_time.timetuple()),
|
|
"exp": timegm(exp_time.timetuple()),
|
|
"protocol_version": "2.0",
|
|
"d_name": "DLS",
|
|
"service_instance_ref": NV_SI_SITE_ID,
|
|
"service_instance_public_key_configuration": {
|
|
"service_instance_public_key_me": {
|
|
"mod": hex(my_si_public_key.public_numbers().n)[2:],
|
|
"exp": int(my_si_public_key.public_numbers().e),
|
|
},
|
|
# 64 chars per line (pem default)
|
|
"service_instance_public_key_pem": my_si_public_key_as_pem.decode('utf-8').strip(),
|
|
"key_retention_mode": "LATEST_ONLY"
|
|
},
|
|
}
|
|
|
|
my_sign_key = jwk.construct(my_si_private_key_as_pem.decode('utf-8'), algorithm=ALGORITHMS.RS256)
|
|
my_config_token = jws.sign(payload, key=my_sign_key, headers=None, algorithm=ALGORITHMS.RS256)
|
|
|
|
# generate a 76 char wide pem (does not work either, so this code can be removed)
|
|
response_ca_chain = my_ca_certificate.public_bytes(encoding=Encoding.PEM).decode('utf-8')
|
|
response_ca_chain = response_ca_chain.replace('-----BEGIN CERTIFICATE-----', '')
|
|
response_ca_chain = response_ca_chain.replace('-----END CERTIFICATE-----', '')
|
|
response_ca_chain = response_ca_chain.replace('\n', '')
|
|
response_ca_chain = wrap(response_ca_chain, 76)
|
|
response_ca_chain = '\r\n'.join(response_ca_chain)
|
|
response_ca_chain = f'-----BEGIN CERTIFICATE-----\r\n{response_ca_chain}\r\n-----END CERTIFICATE-----'
|
|
|
|
response_si_certificate = my_si_certificate.public_bytes(encoding=Encoding.PEM).decode('utf-8')
|
|
response_si_certificate = response_si_certificate.replace('-----BEGIN CERTIFICATE-----', '')
|
|
response_si_certificate = response_si_certificate.replace('-----END CERTIFICATE-----', '')
|
|
response_si_certificate = response_si_certificate.replace('\n', '')
|
|
response_si_certificate = wrap(response_si_certificate, 76)
|
|
response_si_certificate = '\r\n'.join(response_si_certificate)
|
|
response_si_certificate = f'-----BEGIN CERTIFICATE-----\r\n{response_si_certificate}\r\n-----END CERTIFICATE-----'
|
|
|
|
response = {
|
|
"certificateConfiguration": {
|
|
# 76 chars per line
|
|
"caChain": [response_ca_chain],
|
|
# 76 chars per line
|
|
"publicCert": response_si_certificate,
|
|
"publicKey": {
|
|
"exp": int(my_si_certificate.public_key().public_numbers().e),
|
|
"mod": [hex(my_si_certificate.public_key().public_numbers().n)[2:]],
|
|
},
|
|
},
|
|
"configToken": my_config_token,
|
|
}
|
|
|
|
# this would be our response on fastapi-dls
|
|
print(json.dumps(response))
|
|
|
|
#my_si_certificate_as_pem = my_si_certificate.public_bytes(encoding=Encoding.PEM)
|
|
#my_jws_verify_key = jwk.construct(my_si_certificate_as_pem, algorithm=ALGORITHMS.RS256)
|
|
my_response_certificate = x509.load_pem_x509_certificate(response['certificateConfiguration']['publicCert'].encode('utf-8'))
|
|
my_response_certificate_as_pem = my_response_certificate.public_bytes(encoding=Encoding.PEM)
|
|
my_jws_verify_key = jwk.construct(my_response_certificate_as_pem, algorithm=ALGORITHMS.RS256)
|
|
|
|
my_response_config_token = response.get('configToken')
|
|
|
|
payload = jws.verify(my_response_config_token, key=my_jws_verify_key, algorithms=ALGORITHMS.RS256)
|
|
payload = json.loads(payload)
|
|
assert payload.get('iss') == 'NLS Service Instance'
|
|
assert payload.get('aud') == 'NLS Licensed Client'
|
|
assert payload.get('service_instance_ref') == NV_SI_SITE_ID
|
|
|
|
my_si_public_key_configuration = payload.get('service_instance_public_key_configuration')
|
|
my_si_public_key_me = my_si_public_key_configuration.get('service_instance_public_key_me')
|
|
assert my_si_public_key_me.get('mod') == my_si_public_key_mod
|
|
assert my_si_public_key_me.get('exp') == my_si_public_key_exp
|