Example #1
0
    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')
Example #2
0
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)
Example #3
0
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(),
        ))
Example #4
0
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(),
    }
Example #5
0
    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))
Example #6
0
    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,
        )
Example #7
0
    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)
Example #8
0
    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)