예제 #1
0
def test_new_key(context: IntegrationTestsContext) -> None:
    """Tests --new-key and its interactions with --reuse-key"""
    def private_key(generation: int) -> Tuple[str, str]:
        pk_path = join(context.config_dir, f'archive/{certname}/privkey{generation}.pem')
        with open(pk_path, 'r') as file:
            return file.read(), pk_path

    certname = context.get_domain('newkey')

    context.certbot(['--domains', certname, '--reuse-key',
                     '--key-type', 'rsa', '--rsa-key-size', '4096'])
    privkey1, _ = private_key(1)

    # renew: --new-key should replace the key, but keep reuse_key and the key type + params
    context.certbot(['renew', '--cert-name', certname, '--new-key'])
    privkey2, privkey2_path = private_key(2)
    assert privkey1 != privkey2
    assert_saved_lineage_option(context.config_dir, certname, 'reuse_key', 'True')
    assert_rsa_key(privkey2_path, 4096)

    # certonly: it should replace the key but the key size will change
    context.certbot(['certonly', '-d', certname, '--reuse-key', '--new-key'])
    privkey3, privkey3_path = private_key(3)
    assert privkey2 != privkey3
    assert_saved_lineage_option(context.config_dir, certname, 'reuse_key', 'True')
    assert_rsa_key(privkey3_path, 2048)

    # certonly: it should be possible to change the key type and keep reuse_key
    context.certbot(['certonly', '-d', certname, '--reuse-key', '--new-key', '--key-type', 'ecdsa',
                     '--cert-name', certname])
    privkey4, privkey4_path = private_key(4)
    assert privkey3 != privkey4
    assert_saved_lineage_option(context.config_dir, certname, 'reuse_key', 'True')
    assert_elliptic_key(privkey4_path, SECP256R1)
예제 #2
0
def test_revoke_ecdsa_cert_key_delete(context: IntegrationTestsContext,
                                      curve: str,
                                      curve_cls: Type[EllipticCurve],
                                      skip_servers: Iterable[str]) -> None:
    """Test revoke and deletion for each supported curve type"""
    if context.acme_server in skip_servers:
        pytest.skip(
            f'ACME server {context.acme_server} does not support ECDSA curve {curve}'
        )
    cert: str = context.get_domain('curve')
    context.certbot([
        'certonly',
        '--key-type',
        'ecdsa',
        '--elliptic-curve',
        curve,
        '-d',
        cert,
    ])
    key = join(context.config_dir, "live", cert, 'privkey.pem')
    cert_path = join(context.config_dir, "live", cert, 'cert.pem')
    assert_elliptic_key(key, curve_cls)
    context.certbot([
        'revoke',
        '--cert-path',
        cert_path,
        '--key-path',
        key,
        '--delete-after-revoke',
    ])
    assert not exists(cert_path)
예제 #3
0
def test_revoke_ecdsa_cert_key(context: IntegrationTestsContext, curve: str,
                               curve_cls: Type[EllipticCurve],
                               skip_servers: Iterable[str]) -> None:
    """Test revoking a certificate """
    if context.acme_server in skip_servers:
        pytest.skip(
            f'ACME server {context.acme_server} does not support ECDSA curve {curve}'
        )
    cert: str = context.get_domain('curve')
    context.certbot([
        'certonly',
        '--key-type',
        'ecdsa',
        '--elliptic-curve',
        curve,
        '-d',
        cert,
    ])
    key = join(context.config_dir, "live", cert, 'privkey.pem')
    cert_path = join(context.config_dir, "live", cert, 'cert.pem')
    assert_elliptic_key(key, curve_cls)
    context.certbot([
        'revoke',
        '--cert-path',
        cert_path,
        '--key-path',
        key,
        '--no-delete-after-revoke',
    ])
    stdout, _ = context.certbot(['certificates'])
    assert stdout.count(
        'INVALID: REVOKED') == 1, 'Expected {0} to be REVOKED'.format(cert)
예제 #4
0
def test_default_curve_type(context: IntegrationTestsContext) -> None:
    """test that the curve used when not specifying any is secp256r1"""
    certname = context.get_domain('renew')
    context.certbot([
        '--key-type', 'ecdsa', '--cert-name', certname, '-d', certname
    ])
    key1 = join(context.config_dir, 'archive/{0}/privkey1.pem'.format(certname))
    assert_elliptic_key(key1, SECP256R1)
예제 #5
0
def test_ecdsa_curves(context, curve, curve_cls, skip_servers):
    """Test issuance for each supported ECDSA curve"""
    if context.acme_server in skip_servers:
        pytest.skip('ACME server {} does not support ECDSA curve {}'
                    .format(context.acme_server, curve))

    domain = context.get_domain('curve')
    context.certbot([
        'certonly',
        '--key-type', 'ecdsa', '--elliptic-curve', curve,
        '--force-renewal', '-d', domain,
    ])
    key = join(context.config_dir, "live", domain, 'privkey.pem')
    assert_elliptic_key(key, curve_cls)
예제 #6
0
def test_renew_with_ec_keys(context):
    """Test proper renew with updated private key complexity."""
    certname = context.get_domain('renew')
    context.certbot([
        'certonly',
        '--cert-name',
        certname,
        '--key-type',
        'ecdsa',
        '--elliptic-curve',
        'secp256r1',
        '--force-renewal',
        '-d',
        certname,
    ])

    key1 = join(context.config_dir, "archive", certname, 'privkey1.pem')
    assert 200 < os.stat(
        key1).st_size < 250  # ec keys of 256 bits are ~225 bytes
    assert_elliptic_key(key1, SECP256R1)
    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    context.certbot(['renew', '--elliptic-curve', 'secp384r1'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    key2 = join(context.config_dir, 'archive', certname, 'privkey2.pem')
    assert_elliptic_key(key2, SECP384R1)
    assert 280 < os.stat(
        key2).st_size < 320  # ec keys of 384 bits are ~310 bytes

    # We expect here that the command will fail because without --key-type specified,
    # Certbot must error out to prevent changing an existing certificate key type,
    # without explicit user consent (by specifying both --cert-name and --key-type).
    with pytest.raises(subprocess.CalledProcessError):
        context.certbot(['certonly', '--force-renewal', '-d', certname])

    # We expect that the previous behavior of requiring both --cert-name and
    # --key-type to be set to not apply to the renew subcommand.
    context.certbot(['renew', '--force-renewal', '--key-type', 'rsa'])
    assert_cert_count_for_lineage(context.config_dir, certname, 3)
    key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem')
    assert_rsa_key(key3)
예제 #7
0
def test_renew_with_ec_keys(context: IntegrationTestsContext) -> None:
    """Test proper renew with updated private key complexity."""
    certname = context.get_domain('renew')
    context.certbot([
        'certonly',
        '--cert-name', certname,
        '--key-type', 'ecdsa', '--elliptic-curve', 'secp256r1',
        '--force-renewal', '-d', certname,
    ])
    key1 = join(context.config_dir, "archive", certname, 'privkey1.pem')
    assert 200 < os.stat(key1).st_size < 250  # ec keys of 256 bits are ~225 bytes
    assert_elliptic_key(key1, SECP256R1)
    assert_cert_count_for_lineage(context.config_dir, certname, 1)
    assert_saved_lineage_option(context.config_dir, certname, 'key_type', 'ecdsa')

    context.certbot(['renew', '--elliptic-curve', 'secp384r1'])
    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    key2 = join(context.config_dir, 'archive', certname, 'privkey2.pem')
    assert 280 < os.stat(key2).st_size < 320  # ec keys of 384 bits are ~310 bytes
    assert_elliptic_key(key2, SECP384R1)

    # When running non-interactively, if --key-type is unspecified but the default value differs
    # to the lineage key type, Certbot should keep the lineage key type. The curve will still
    # change to the default value, in order to stay consistent with the behavior of certonly.
    context.certbot(['certonly', '--force-renewal', '-d', certname])
    assert_cert_count_for_lineage(context.config_dir, certname, 3)
    key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem')
    assert 200 < os.stat(key3).st_size < 250  # ec keys of 256 bits are ~225 bytes
    assert_elliptic_key(key3, SECP256R1)

    # When running non-interactively, specifying a different --key-type requires user confirmation
    # with both --key-type and --cert-name.
    with pytest.raises(subprocess.CalledProcessError) as error:
        context.certbot(['certonly', '--force-renewal', '-d', certname,
                         '--key-type', 'rsa'])
    assert 'Please provide both --cert-name and --key-type' in error.value.stderr

    context.certbot(['certonly', '--force-renewal', '-d', certname,
                     '--key-type', 'rsa', '--cert-name', certname])
    assert_cert_count_for_lineage(context.config_dir, certname, 4)
    key4 = join(context.config_dir, 'archive', certname, 'privkey4.pem')
    assert_rsa_key(key4)

    # We expect that the previous behavior of requiring both --cert-name and
    # --key-type to be set to not apply to the renew subcommand.
    context.certbot(['renew', '--force-renewal', '--key-type', 'ecdsa'])
    assert_cert_count_for_lineage(context.config_dir, certname, 5)
    key5 = join(context.config_dir, 'archive', certname, 'privkey5.pem')
    assert 200 < os.stat(key5).st_size < 250  # ec keys of 256 bits are ~225 bytes
    assert_elliptic_key(key5, SECP256R1)