def test_load_config():
    config = BlessConfig()
    configIO = StringIO(TEST_CONFIG)
    conf = config.parse_config_file(configIO)
    assert conf == {
        'KMSAUTH_CONFIG_SFO': {
            'kmskey': 'abcdefgh-0123-4567-8910-abcdefghijkl',
            'awsregion': 'us-west-2',
            'context': {
                'to': 'bless-production',
                'user_type': 'user'
            }
        },
        'KMSAUTH_CONFIG_IAD': {
            'kmskey': 'zxywvuts-0123-4567-8910-abcdefghijkl',
            'awsregion': 'us-east-1',
            'context': {
                'to': 'bless-production',
                'user_type': 'user'
            }
        },
        'REGION_ALIAS': {
            'IAD': 'us-east-1',
            'SFO': 'us-west-2'
        },
        'BLESS_CONFIG': {
            'ipcachelifetime': 60,
            'functionname': 'lyft_bless',
            'functionversion': 'PROD-1-2',
            'userrole': 'use-bless',
            'timeoutconfig': {
                'read': 10,
                'connect': 5
            },
            'certlifetime': 120,
            'accountid': '111111111111'
        },
        'AWS_CONFIG': {
            'bastion_ips': '10.0.0.0/8,192.168.192.1',
            'remote_user': '******'
        },
        'CLIENT_CONFIG': {
            'domain_regex':
            '(i-.*|.*\\.example\\.com|\\A10\\.0(?:\\.[0-9]{1,3}){2}\\Z)$',
            'cache_file': 'bless_cache.json',
            'mfa_cache_dir': '.aws-mfa/session',
            'cache_dir': '.aws-mfa/session',
            'mfa_cache_file': 'token_cache.json',
            'ip_urls':
            ['http://checkip.amazonaws.com', 'http://api.ipify.org'],
            'update_script': 'autoupdate.sh',
            'user_session_length': 3600,
            'usebless_role_session_length':
            3600,  # comes from BlessConfig.DEFAULT_CONFIG
            'update_sshagent': False
        }
    }
Пример #2
0
def bless_config():
    bc = BlessConfig()
    bc.set_config({
        'REGION_ALIAS': {
            'IAD': 'us-east-1',
            'SFO': 'us-west-2'
        },
        'BLESS_CONFIG': {
            'ipcachelifetime': 300,
            'functionname': 'lyft_bless',
            'functionversion': 'PROD-1-2',
            'userrole': 'role_bar',
            'timeoutconfig': {
                'read': 10,
                'connect': 5
            },
            'certlifetime': 1800,
            'accountid': '111111111111'
        },
        'CLIENT_CONFIG': {
            'ip_urls': 'http://api.ipify.org, http://canihazip.com',
            'domain_regex':
            '(i-.*|.*\\.example\\.com|\\A10\\.0(?:\\.[0-9]{1,3}){2}\\Z)$',
            'cache_dir': '.aws-mfa/session',
            'cache_file': 'bless_cache.json',
            'mfa_cache_dir': '.aws-mfa/session',
            'mfa_cache_file': 'token_cache.json',
            'update_script': 'autoupdate.sh',
        },
        'KMSAUTH_CONFIG_SFO': {
            'kmskey': 'abcdefgh-0123-4567-8910-abcdefghijkl',
            'awsregion': 'us-west-2',
            'context': {
                'to': 'bless-production',
                'user_type': 'user'
            }
        },
        'KMSAUTH_CONFIG_IAD': {
            'kmskey': 'zxywvuts-0123-4567-8910-abcdefghijkl',
            'awsregion': 'us-east-1',
            'context': {
                'to': 'bless-production',
                'user_type': 'user'
            }
        },
        'VAULT_CONFIG': {
            'vault_addr': 'https://vault.example.com:1234',
            'auth_mount': 'okta',
            'ssh_backend_mount': 'ssh-client-signer',
            'ssh_backend_role': 'bless'
        }
    })
    return bc
Пример #3
0
def test_load_vault_config():
    config = BlessConfig()
    configIO = StringIO(VAULT_CONFIG + TEST_CONFIG)
    conf = config.parse_config_file(configIO)
    expectedConf = BASE_EXPECTED_CONF
    expectedConf['VAULT_CONFIG'] = {
        'vault_addr': 'https://vault.example.com:1234',
        'auth_mount': 'okta',
        'ssh_backend_mount': 'ssh-client-signer',
        'ssh_backend_role': 'bless'
    }
    expectedConf['BLESS_CONFIG']['ca_backend'] = "hashicorp-vault"
    assert conf == expectedConf
Пример #4
0
def bless_config():
    bc = BlessConfig()
    bc.set_config({
        'REGION_ALIAS': {
            'IAD': 'us-east-1',
            'SFO': 'us-west-2'
        },
        'BLESS_CONFIG': {
            'ipcachelifetime': 300,
            'functionname': 'lyft_bless',
            'functionversion': 'PROD-1-2',
            'userrole': 'role_bar',
            'timeoutconfig': {
                'read': 10,
                'connect': 5
            },
            'certlifetime': 1800,
            'accountid': '111111111111'
        },
        'CLIENT_CONFIG': {
            'domain_regex':
            '(i-.*|.*\\.example\\.com|\\A10\\.0(?:\\.[0-9]{1,3}){2}\\Z)$',
            'cache_dir': '.aws-mfa/session',
            'cache_file': 'bless_cache.json',
            'mfa_cache_dir': '.aws-mfa/session',
            'mfa_cache_file': 'token_cache.json',
            'update_script': 'autoupdate.sh',
        },
        'KMSAUTH_CONFIG_SFO': {
            'kmskey': 'abcdefgh-0123-4567-8910-abcdefghijkl',
            'awsregion': 'us-west-2',
            'context': {
                'to': 'bless-production',
                'user_type': 'user'
            }
        },
        'KMSAUTH_CONFIG_IAD': {
            'kmskey': 'zxywvuts-0123-4567-8910-abcdefghijkl',
            'awsregion': 'us-east-1',
            'context': {
                'to': 'bless-production',
                'user_type': 'user'
            }
        }
    })
    return bc
Пример #5
0
def main():
    parser = argparse.ArgumentParser(description='Bless SSH')
    parser.add_argument('host')
    parser.add_argument('cmd', nargs='*')
    parser.add_argument('--nocache', action='store_true')
    parser.add_argument(
        '--config',
        default=None,
        help='Config file for blessclient. Default to ~/.aws/blessclient.cfg')
    parser.add_argument(
        '--download_config',
        action='store_true',
        help=
        'Download blessclient.cfg from S3 bucket. Will overwrite if file already exist'
    )
    parser.add_argument('-4',
                        action='store_true',
                        help='Forces ssh to use IPv4 addresses only.')
    parser.add_argument('-6',
                        action='store_true',
                        help='Forces ssh to use IPv6 addresses only.')
    parser.add_argument(
        '-a',
        action='store_true',
        help='Disable forwarding of the authentication agent connection.')
    parser.add_argument('-X',
                        action='store_true',
                        help='Enables X11 forwarding.')
    parser.add_argument('-Y',
                        action='store_true',
                        help='Enables trusted X11 forwarding.')
    parser.add_argument(
        '-l',
        default=None,
        help=
        'Specifies the user to log in as on the remote machine. Defaults to IAM user'
    )
    parser.add_argument(
        '-p',
        default=22,
        help='Port to connect to on the remote host. Default 22')
    parser.add_argument(
        '-F',
        default=None,
        help='Specifies an alternative per-user configuration file for ssh.')
    args = parser.parse_args()

    if 'AWS_PROFILE' not in os.environ:
        sys.stderr.write(
            'AWS session not found. Try running get_session first?\n')
        sys.exit(1)

    if 'AWS_EXPIRATION_S' in os.environ:
        expiration = datetime.datetime.fromtimestamp(
            int(os.environ['AWS_EXPIRATION_S']))
        if expiration < datetime.datetime.now():
            sys.stderr.write(
                'AWS session expired. Try running get_session first?\n')
            sys.exit(1)

    try:
        ssh_version = re.search(
            'OpenSSH_([^\s]+)',
            subprocess.check_output(['ssh', '-V'],
                                    stderr=subprocess.STDOUT).decode('UTF-8'))
        if '7.8' in ssh_version.group(0):
            sys.stderr.write("""@@@@@@@ WARNING @@@@@@@
There is a bug in OpenSSH version 7.8 that makes signed ssh keys not work, and thus Bless does not work.
From our knowledge, the bug only affects the ssh client.
sshd version 7.7 or 7.9 should work with Bless.
We detected that you are running {}
""".format(ssh_version.group(0)) + '\n' + '-' * 64)
    except Exception as e:
        sys.stderr.write('Failed to get OpenSSH client version\n')

    ssh_options = []
    if vars(args)['4']:
        ssh_options.append('-4')
    if vars(args)['6']:
        if vars(args)['4']:
            sys.stderr.write('ERROR: -4 and -6 are mutually exclusive...\n')
            sys.exit(1)
        ssh_options.append('-6')
    if not args.a:
        ssh_options.append('-A')
    if args.X:
        ssh_options.append('-X')
    if args.Y:
        ssh_options.append('-Y')
    if args.F is not None:
        ssh_options.append('-F')
        ssh_options.append(args.F)

    hostname = None
    username = None
    port = args.p

    host = args.host.split('@')
    if len(host) == 2:
        hostname = host[1]
        username = host[0]
    else:
        hostname = host[0]

    host = hostname.split(':')
    if len(host) == 2:
        hostname = host[0]
        port = host[1]

    ssh_options.append('-p')
    ssh_options.append(str(port))

    if args.l is not None:
        username = args.l

    blessclient_output = []
    bless_config = BlessConfig()

    if load_config(bless_config, args.config, args.download_config) is False:
        sys.exit(1)

    start_region = get_region_from_code(None, bless_config)
    for region in get_regions(start_region, bless_config):
        try:
            os.environ['BLESSQUIET'] = "1"
            blessclient_output = bless(region, args.nocache, False, hostname,
                                       bless_config, username)
            break
        except SystemExit:
            pass

    if blessclient_output == []:
        sys.exit(1)

    if 'username' in blessclient_output:
        ssh_options.append('-l')
        ssh_options.append(blessclient_output['username'])
    elif username is not None:
        ssh_options.append('-l')
        ssh_options.append(username)

    if len(args.cmd) >= 1:
        for cmd in args.cmd:
            ssh_options.append(cmd)

    subprocess.call(['ssh', hostname] + ssh_options)
Пример #6
0
def test_load_bless_config():
    config = BlessConfig()
    configIO = StringIO(BLESS_CONFIG + TEST_CONFIG)
    conf = config.parse_config_file(configIO)
    assert conf == BASE_EXPECTED_CONF
Пример #7
0
def test_get_config():
    config = BlessConfig()
    config.blessconfig = {'foo': 'bar'}
    assert config.get_config() == {'foo': 'bar'}
Пример #8
0
def test_get_invalid():
    config = BlessConfig()
    config.blessconfig = {'foo': 'bar'}
    with pytest.raises(ValueError):
        config.get('DOESNOTEXIST')
Пример #9
0
def test_set():
    config = BlessConfig()
    config.set_config({'foo': 'bar'})
    assert config.blessconfig['foo'] == 'bar'
Пример #10
0
def bless_config_test():
    configIO = StringIO(BLESS_CONFIG + TEST_CONFIG)
    config = BlessConfig()
    config.set_config(config.parse_config_file(configIO))
    return config