Esempio n. 1
0
def test_certonly_webroot(context: IntegrationTestsContext) -> None:
    """Test the certonly verb with webroot plugin"""
    with misc.create_http_server(context.http_01_port) as webroot:
        certname = context.get_domain('webroot')
        context.certbot(['certonly', '-a', 'webroot', '--webroot-path', webroot, '-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)
Esempio n. 2
0
def test_manual_dns_auth(context):
    """Test the DNS-01 challenge using manual plugin."""
    certname = context.get_domain('dns')
    context.certbot([
        '-a',
        'manual',
        '-d',
        certname,
        '--preferred-challenges',
        'dns',
        'run',
        '--cert-name',
        certname,
        '--manual-auth-hook',
        context.manual_dns_auth_hook,
        '--manual-cleanup-hook',
        context.manual_dns_cleanup_hook,
        '--pre-hook',
        misc.echo('wtf_pre', context.hook_probe),
        '--post-hook',
        misc.echo('wtf_post', context.hook_probe),
        '--renew-hook',
        misc.echo('renew', context.hook_probe),
    ])

    with pytest.raises(AssertionError):
        assert_hook_execution(context.hook_probe, 'renew')
    assert_saved_renew_hook(context.config_dir, certname)

    context.certbot(
        ['renew', '--cert-name', certname, '--authenticator', 'manual'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
Esempio n. 3
0
def test_certonly(context: IntegrationTestsContext) -> None:
    """Test the certonly verb on certbot."""
    context.certbot([
        'certonly', '--cert-name', 'newname', '-d',
        context.get_domain('newname')
    ])

    assert_cert_count_for_lineage(context.config_dir, 'newname', 1)
Esempio n. 4
0
def test_renew_with_hook_scripts(context):
    """Test certificate renewal with script hooks."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    misc.generate_test_file_hooks(context.config_dir, context.hook_probe)
    context.certbot(['renew'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    assert_hook_execution(context.hook_probe, 'deploy')
Esempio n. 5
0
def test_renew_ignoring_directory_hooks(context):
    """Test hooks are ignored during renewal with relevant CLI flag."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    misc.generate_test_file_hooks(context.config_dir, context.hook_probe)
    context.certbot(['renew', '--no-directory-hooks'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    with pytest.raises(AssertionError):
        assert_hook_execution(context.hook_probe, 'deploy')
Esempio n. 6
0
def test_graceful_renew_it_is_not_time(context):
    """Test graceful renew is not done when it is not due time."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    context.certbot(['renew', '--deploy-hook', 'echo deploy >> "{0}"'.format(context.hook_probe)],
                    force_renew=False)

    assert_cert_count_for_lineage(context.config_dir, certname, 1)
    with pytest.raises(AssertionError):
        assert_hook_execution(context.hook_probe, 'deploy')
Esempio n. 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)
Esempio n. 8
0
def test_renew_empty_hook_scripts(context):
    """Test proper renew with empty hook scripts."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    misc.generate_test_file_hooks(context.config_dir, context.hook_probe)
    for hook_dir in misc.list_renewal_hooks_dirs(context.config_dir):
        shutil.rmtree(hook_dir)
        os.makedirs(join(hook_dir, 'dir'))
        open(join(hook_dir, 'file'), 'w').close()
    context.certbot(['renew'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
Esempio n. 9
0
def test_renew_files_propagate_permissions(context):
    """Test proper certificate renewal with custom permissions propagated on private key."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    os.chmod(join(context.config_dir, 'archive', certname, 'privkey1.pem'), 0o444)
    context.certbot(['renew'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    assert_world_permissions(
        join(context.config_dir, 'archive', certname, 'privkey2.pem'), 4)
    assert_equals_permissions(
        join(context.config_dir, 'archive', certname, 'privkey1.pem'),
        join(context.config_dir, 'archive', certname, 'privkey2.pem'), 0o074)
Esempio n. 10
0
def test_graceful_renew_it_is_time(context):
    """Test graceful renew is done when it is due time."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    with open(join(context.config_dir, 'renewal', '{0}.conf'.format(certname)), 'r') as file:
        lines = file.readlines()
    lines.insert(4, 'renew_before_expiry = 100 years{0}'.format(os.linesep))
    with open(join(context.config_dir, 'renewal', '{0}.conf'.format(certname)), 'w') as file:
        file.writelines(lines)

    context.certbot(['renew', '--deploy-hook', 'echo deploy >> "{0}"'.format(context.hook_probe)],
                    force_renew=False)

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    assert_hook_execution(context.hook_probe, 'deploy')
Esempio n. 11
0
def test_renew_files_permissions(context: IntegrationTestsContext) -> None:
    """Test proper certificate file permissions upon renewal"""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    privkey1 = join(context.config_dir, 'archive', certname, 'privkey1.pem')
    privkey2 = join(context.config_dir, 'archive', certname, 'privkey2.pem')

    assert_cert_count_for_lineage(context.config_dir, certname, 1)
    assert_world_no_permissions(privkey1)

    context.certbot(['renew'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    assert_world_no_permissions(privkey2)
    assert_equals_group_owner(privkey1, privkey2)
    assert_equals_world_read_permissions(privkey1, privkey2)
    assert_equals_group_permissions(privkey1, privkey2)
Esempio n. 12
0
def test_renew_files_propagate_permissions(
        context: IntegrationTestsContext) -> None:
    """Test proper certificate renewal with custom permissions propagated on private key."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    privkey1 = join(context.config_dir, 'archive', certname, 'privkey1.pem')
    privkey2 = join(context.config_dir, 'archive', certname, 'privkey2.pem')

    if os.name != 'nt':
        os.chmod(privkey1, 0o444)
    else:
        import win32security  # pylint: disable=import-error
        import ntsecuritycon  # pylint: disable=import-error
        # Get the current DACL of the private key
        security = win32security.GetFileSecurity(
            privkey1, win32security.DACL_SECURITY_INFORMATION)
        dacl = security.GetSecurityDescriptorDacl()
        # Create a read permission for Everybody group
        everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID)
        dacl.AddAccessAllowedAce(win32security.ACL_REVISION,
                                 ntsecuritycon.FILE_GENERIC_READ, everybody)
        # Apply the updated DACL to the private key
        security.SetSecurityDescriptorDacl(1, dacl, 0)
        win32security.SetFileSecurity(privkey1,
                                      win32security.DACL_SECURITY_INFORMATION,
                                      security)

    context.certbot(['renew'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    if os.name != 'nt':
        # On Linux, read world permissions + all group permissions
        # will be copied from the previous private key
        assert_world_read_permissions(privkey2)
        assert_equals_world_read_permissions(privkey1, privkey2)
        assert_equals_group_permissions(privkey1, privkey2)
    else:
        # On Windows, world will never have any permissions, and
        # group permission is irrelevant for this platform
        assert_world_no_permissions(privkey2)
Esempio n. 13
0
def test_renew_files_permissions(context):
    """Test proper certificate file permissions upon renewal"""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname])

    assert_cert_count_for_lineage(context.config_dir, certname, 1)
    assert_world_permissions(
        join(context.config_dir, 'archive', certname, 'privkey1.pem'), 0)

    context.certbot(['renew'])

    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    assert_world_permissions(
        join(context.config_dir, 'archive', certname, 'privkey2.pem'), 0)
    assert_equals_group_owner(
        join(context.config_dir, 'archive', certname, 'privkey1.pem'),
        join(context.config_dir, 'archive', certname, 'privkey2.pem'))
    assert_equals_permissions(
        join(context.config_dir, 'archive', certname, 'privkey1.pem'),
        join(context.config_dir, 'archive', certname, 'privkey2.pem'), 0o074)
Esempio n. 14
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

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

    assert_cert_count_for_lineage(context.config_dir, certname, 3)
    key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem')
    assert_elliptic_key(key3, SECP521R1)
    assert 340 < os.stat(key3).st_size < 390  # ec keys of 521 bits are ~365 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, 4)
    key4 = join(context.config_dir, 'archive', certname, 'privkey4.pem')
    assert_rsa_key(key4)
Esempio n. 15
0
def test_ocsp_renew(context: IntegrationTestsContext) -> None:
    """Test that revoked certificates are renewed."""
    # Obtain a certificate
    certname = context.get_domain('ocsp-renew')
    context.certbot(['--domains', certname])

    # Test that "certbot renew" does not renew the certificate
    assert_cert_count_for_lineage(context.config_dir, certname, 1)
    context.certbot(['renew'], force_renew=False)
    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    # Revoke the certificate and test that it does renew the certificate
    context.certbot(['revoke', '--cert-name', certname, '--no-delete-after-revoke'])
    context.certbot(['renew'], force_renew=False)
    assert_cert_count_for_lineage(context.config_dir, certname, 2)
Esempio n. 16
0
def test_renew_with_changed_private_key_complexity(context):
    """Test proper renew with updated private key complexity."""
    certname = context.get_domain('renew')
    context.certbot(['-d', certname, '--rsa-key-size', '4096'])

    key1 = join(context.config_dir, 'archive', certname, 'privkey1.pem')
    assert os.stat(key1).st_size > 3000  # 4096 bits keys takes more than 3000 bytes
    assert_cert_count_for_lineage(context.config_dir, certname, 1)

    context.certbot(['renew'])
    
    assert_cert_count_for_lineage(context.config_dir, certname, 2)
    key2 = join(context.config_dir, 'archive', certname, 'privkey2.pem')
    assert os.stat(key2).st_size > 3000

    context.certbot(['renew', '--rsa-key-size', '2048'])

    assert_cert_count_for_lineage(context.config_dir, certname, 3)
    key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem')
    assert os.stat(key3).st_size < 1800  # 2048 bits keys takes less than 1800 bytes