def get_kmsauth_token(creds, config, username, cache):
    cache_key = 'kmsauth-{}'.format(config['awsregion'])
    kmsauth_cache = cache.get(cache_key)
    if kmsauth_cache:
        expiration = time.strptime(kmsauth_cache['Expiration'],
                                   '%Y%m%dT%H%M%SZ')
        if expiration > time.gmtime() and kmsauth_cache['token'] is not None:
            logging.debug('Using cached kmsauth token, good until {}'.format(
                kmsauth_cache['Expiration']))
            return kmsauth_cache['token']

    config['context'].update({'from': username})
    try:
        token = kmsauth.KMSTokenGenerator(
            config['kmskey'],
            config['context'],
            config['awsregion'],
            aws_creds=creds,
            token_lifetime=60).get_token().decode('US-ASCII')
    except kmsauth.ServiceConnectionError:
        logging.debug("Network failure for kmsauth")
        raise LambdaInvocationException(
            'Connection error getting kmsauth token.')
    # We have to manually calculate expiration the same way kmsauth does
    lifetime = 60 - (kmsauth.TOKEN_SKEW * 2)
    if lifetime > 0:
        expiration = datetime.datetime.utcnow() + datetime.timedelta(
            minutes=lifetime)
        kmsauth_cache = {
            'token': token,
            'Expiration': expiration.strftime('%Y%m%dT%H%M%SZ')
        }
        cache.set(cache_key, kmsauth_cache)
        cache.save()
    return token
Exemple #2
0
 def _get_generator(self, action, resource):
     generator = kmsauth.KMSTokenGenerator(
         # KMS key to use for authentication to the lambda
         self.kmsauth_key,
         # Encryption context to use
         {
             # We're authenticating to this service
             'to': self.to_context,
             # It's from this IAM role
             'from': self.from_context,
             # This token is for a service
             'user_type': self.user_type_context,
             # This is an association action
             'action': action,
             'resource': resource
         },
         # Find the KMS key in this region
         'us-east-1')
     return generator
Exemple #3
0
    def generate_user_token(self, user):
        '''
        Question: what kinda access control is it if I have direct access to the authorization key, generate it myself?
                  You'd probably get something handed to you by https://lyft.github.io/confidant/
        
        :param user: 
        :return:
        
        '''
        if not KMS_AUTH:
            raise ValueError("kmsauth is not installed")

        ## prompt for session
        mfa_creds = self.get_mfa_session(self.kmsauth_mfa_serial)

        # user to service authentication
        generator = kmsauth.KMSTokenGenerator(
            # KMS key to use for authentication
            self.kmsauth_autogen_key,

            # Encryption context to use
            {
                # We're authenticating to this service
                'to': self.kmsauth_autogen_service,
                # It's from this user
                'from': user,
                # This token is for a user
                'user_type': 'user'
            },
            # Find the KMS key in this region
            self.region,
            aws_creds=mfa_creds)
        username = generator.get_username()
        token = generator.get_token()

        return username, token
Exemple #4
0
    def __init__(self,
                 url=None,
                 auth_key=None,
                 auth_context=None,
                 token_lifetime=None,
                 token_version=None,
                 token_cache_file=None,
                 assume_role=None,
                 mfa_pin=None,
                 region=None,
                 retries=None,
                 backoff=None,
                 config_files=None,
                 profile=None,
                 verify=None):
        """Create a ConfidantClient object.

        Args:
            url: URL of confidant server. Default: None
            auth_key: The KMS key ARN or alias to use for authentication.
                Default: None
            auth_context: The KMS encryption context to use for authentication.
                Default: None
            token_lifetime: Lifetime of the authentication token generated.
                Default: 10
            token_version: The version of the authentication token. Default: 2
            token_cache_file: The location to use for caching the auth token.
                If set to empty string, no cache will be used. Default:
                /dev/shm/confidant/confidant_token
            assume_role: IAM role to assume for getting KMS auth token.
                Default: None
            mfa_pin: pin to use when assuming a role or getting an MFA session.
                Default: None
            region: AWS region to connect to. Default: None.
            retries: Number of retries to use on failed requests. Default: 0
            backoff: Backoff factor for retries. See urllib3's Retry helper.
                Default: 1
            config_files: A list of config files to attempt to load
            configuration from. First file found will be used. Default:
                ['~/.confidant', '/etc/confidant/config']
            profile: profile to read config values from.
            verify:  Whether we verify the servers TLS certificate.
        """
        # Set defaults
        self.config = {
            'url': None,
            'auth_key': None,
            'auth_context': {},
            'token_lifetime': 10,
            'token_version': 2,
            'token_cache_file': '/dev/shm/confidant/confidant_token',
            'assume_role': None,
            'region': None,
            'retries': 0,
            'backoff': 1,
            'verify': True
        }
        if config_files is None:
            config_files = ['~/.confidant', '/etc/confidant/config']
        if profile is None:
            profile = 'default'
        # Override defaults from config file
        self.config.update(self._load_config(config_files, profile))
        # Override config from passed-in args
        args_config = {
            'url': url,
            'auth_key': auth_key,
            'auth_context': auth_context,
            'token_lifetime': token_lifetime,
            'token_version': token_version,
            'token_cache_file': token_cache_file,
            'region': region,
            'backoff': backoff,
            'assume_role': assume_role,
            'verify': verify
        }
        for key, val in args_config.items():
            if val is not None:
                self.config[key] = val
        # Use session to re-try failed requests.
        self.request_session = requests.Session()
        self.request_session.verify = self.config['verify']
        for proto in ['http://', 'https://']:
            self.request_session.mount(
                proto,
                HTTPAdapter(
                    max_retries=Retry(total=self.config['retries'],
                                      status_forcelist=[500, 503],
                                      backoff_factor=self.config['backoff'])))
        self.iam_client = confidant_client.services.get_boto_client(
            'iam', region=self.config['region'])
        self._load_user_auth_context()
        self._validate_client()
        self.sts_client = confidant_client.services.get_boto_client(
            'sts', region=self.config['region'])
        self.kms_client = confidant_client.services.get_boto_client(
            'kms', region=self.config['region'])
        if self.config['assume_role']:
            self.aws_creds = self._get_assume_role_creds(
                self.config['assume_role'], mfa_pin)
        elif mfa_pin:
            self.aws_creds = self._get_mfa_creds(mfa_pin)
        else:
            self.aws_creds = None
        try:
            self.generator = kmsauth.KMSTokenGenerator(
                self.config['auth_key'],
                self.config['auth_context'],
                self.config['region'],
                token_version=self.config['token_version'],
                token_cache_file=self.config['token_cache_file'],
                token_lifetime=self.config['token_lifetime'],
                aws_creds=self.aws_creds)
        except kmsauth.ConfigurationError:
            raise ClientConfigurationError('Error configuring kmsauth client.')