def test_generate_keys(self): key = JsonWebKey.generate_key(kty='oct', crv_or_size=256, is_private=True) self.assertEqual(key['kty'], 'oct') key = JsonWebKey.generate_key(kty='EC', crv_or_size='P-256') self.assertEqual(key['kty'], 'EC') key = JsonWebKey.generate_key(kty='RSA', crv_or_size=2048) self.assertEqual(key['kty'], 'RSA') key = JsonWebKey.generate_key(kty='OKP', crv_or_size='Ed25519') self.assertEqual(key['kty'], 'OKP')
def generate_service_key(service, expiration_date, kid=None, name="", metadata=None, rotation_duration=None): """ 'kid' will default to the jwk thumbprint if not set explicitly. Reference: https://tools.ietf.org/html/rfc7638 """ options = {} if kid: options["kid"] = kid jwk = JsonWebKey.generate_key("RSA", 2048, is_private=True, options=options) kid = jwk.as_dict()["kid"] key = create_service_key( name, kid, service, jwk.as_dict(), metadata or {}, expiration_date, rotation_duration=rotation_duration, ) return (jwk.get_private_key(), key)
def generate_key_pair(filename, kid=None): """ 'kid' will default to the jwk thumbprint if not set explicitly. Reference: https://tools.ietf.org/html/rfc7638 """ options = {} if kid: options["kid"] = kid jwk = JsonWebKey.generate_key("RSA", 2048, is_private=True, options=options) print(("Writing public key to %s.jwk" % filename)) with open("%s.jwk" % filename, mode="w") as f: f.truncate(0) f.write(jwk.as_json()) print(("Writing key ID to %s.kid" % filename)) with open("%s.kid" % filename, mode="w") as f: f.truncate(0) f.write(jwk.as_dict()["kid"]) print(("Writing private key to %s.pem" % filename)) with open("%s.pem" % filename, mode="wb") as f: f.truncate(0) f.write(jwk.get_private_key().private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ))
def signing_key(): jwk = JsonWebKey.generate_key("RSA", 2048, is_private=True) return { "id": "somekey", "private_key": jwk.get_private_key().private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ), "jwk": jwk.as_dict(), }
def generateRSAKeys(self): """Generate an RSA keypair with an exponent of 65537 in PEM format :return: S_OK/S_ERROR """ key = JsonWebKey.generate_key("RSA", 1024, is_private=True) # as_dict has no arguments for authlib < 1.0.0 # for authlib >= 1.0.0 keyDict = dict(key=json.dumps(key.as_dict(True)), kid=key.thumbprint(), expires_at=time.time() + (30 * 24 * 3600)) session = self.session() try: session.add(JWK(**keyDict)) except Exception as e: return self.__result(session, S_ERROR("Could not generate keys: %s" % e)) return self.__result(session, S_OK(keyDict))
def test_put_service_key(self): # No Authorization header should yield a 400 self.putResponse( "key_server.put_service_key", service="sample_service", kid="kid420", expected_code=400 ) # Mint a JWT with our test payload jwk = JsonWebKey.generate_key("RSA", 2048, is_private=True) private_pem = jwk.get_private_key().private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) payload = self._get_test_jwt_payload() token = jwt.encode(payload, private_pem, "RS256") # Invalid service name should yield a 400. self.putResponse( "key_server.put_service_key", service="sample service", kid="kid420", headers={ "Authorization": "Bearer %s" % token.decode("ascii"), "Content-Type": "application/json", }, data=jwk.as_dict(), expected_code=400, ) # Publish a new key with assert_action_logged("service_key_create"): self.putResponse( "key_server.put_service_key", service="sample_service", kid="kid420", headers={ "Authorization": "Bearer %s" % token.decode("ascii"), "Content-Type": "application/json", }, data=jwk.as_dict(), expected_code=202, ) # Ensure that the key exists but is unapproved. self.getResponse( "key_server.get_service_key", service="sample_service", kid="kid420", expected_code=409 ) # Attempt to rotate the key. Since not approved, it will fail. token = jwt.encode(payload, private_pem, "RS256", headers={"kid": "kid420"}) self.putResponse( "key_server.put_service_key", service="sample_service", kid="kid6969", headers={ "Authorization": "Bearer %s" % token.decode("ascii"), "Content-Type": "application/json", }, data=jwk.as_dict(), expected_code=403, ) # Approve the key. model.service_keys.approve_service_key( "kid420", ServiceKeyApprovalType.SUPERUSER, approver=1 ) # Rotate that new key with assert_action_logged("service_key_rotate"): token = jwt.encode(payload, private_pem, "RS256", headers={"kid": "kid420"}) self.putResponse( "key_server.put_service_key", service="sample_service", kid="kid6969", headers={ "Authorization": "Bearer %s" % token.decode("ascii"), "Content-Type": "application/json", }, data=jwk.as_dict(), expected_code=200, ) # Rotation should only work when signed by the previous key jwk = JsonWebKey.generate_key("RSA", 2048, is_private=True) private_pem = jwk.get_private_key().private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) token = jwt.encode(payload, private_pem, "RS256", headers={"kid": "kid420"}) self.putResponse( "key_server.put_service_key", service="sample_service", kid="kid6969", headers={ "Authorization": "Bearer %s" % token.decode("ascii"), "Content-Type": "application/json", }, data=jwk.as_dict(), expected_code=403, )
app.config["SERVER_HOSTNAME"], app.config["HTTPCLIENT"], instance_keys=instance_keys, ) tuf_metadata_api = TUFMetadataAPI(app, app.config) # Check for a key in config. If none found, generate a new signing key for Docker V2 manifests. _v2_key_path = os.path.join(OVERRIDE_CONFIG_DIRECTORY, DOCKER_V2_SIGNINGKEY_FILENAME) if os.path.exists(_v2_key_path): with open(_v2_key_path) as key_file: docker_v2_signing_key = JsonWebKey.import_key(key_file.read()) else: docker_v2_signing_key = JsonWebKey.generate_key("RSA", 2048, is_private=True) # Configure the database. if app.config.get("DATABASE_SECRET_KEY") is None and app.config.get( "SETUP_COMPLETE", False): raise Exception( "Missing DATABASE_SECRET_KEY in config; did you perhaps forget to add it?" ) database.configure(app.config) model.config.app_config = app.config model.config.store = storage model.config.register_repo_cleanup_callback(tuf_metadata_api.delete_metadata)
def _get_oidc_mocks(self): kid = "somekey" generatedjwk = JsonWebKey.generate_key("RSA", 2048, is_private=True, options={"kid": kid}) private_pem = generatedjwk.get_private_key().private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) token_data = { "iss": app.config["TESTOIDC_LOGIN_CONFIG"]["OIDC_SERVER"], "aud": app.config["TESTOIDC_LOGIN_CONFIG"]["CLIENT_ID"], "nbf": int(time.time()), "iat": int(time.time()), "exp": int(time.time() + 600), "sub": "cool.user", } token_headers = { "kid": kid, } id_token = jwt.encode(token_data, private_pem, "RS256", headers=token_headers) @urlmatch(netloc=r"fakeoidc", path="/token") def token_handler(_, request): if request.body.find("code=somecode") >= 0: content = { "access_token": "someaccesstoken", "id_token": id_token.decode("ascii") } return py_json.dumps(content) else: return { "status_code": 400, "content": '{"message": "Invalid code"}' } @urlmatch(netloc=r"fakeoidc", path="/user") def user_handler(_, __): content = { "sub": "cool.user", "preferred_username": "******", "email": "*****@*****.**", "email_verified": True, } return py_json.dumps(content) @urlmatch(netloc=r"fakeoidc", path="/jwks") def jwks_handler(_, __): jwk = generatedjwk.as_dict().copy() jwk.update({"kid": kid}) content = {"keys": [jwk]} return py_json.dumps(content) @urlmatch(netloc=r"fakeoidc", path=".+openid.+") def discovery_handler(_, __): content = { "scopes_supported": ["profile"], "authorization_endpoint": "http://fakeoidc/authorize", "token_endpoint": "http://fakeoidc/token", "userinfo_endpoint": "http://fakeoidc/userinfo", "jwks_uri": "http://fakeoidc/jwks", } return py_json.dumps(content) return (discovery_handler, jwks_handler, token_handler, user_handler)