예제 #1
0
    def get_token(self):
        """
        Return bearer token
        """
        session = boto3.session.Session()
        # Get ServiceID required by class RequestSigner
        client = session.client("sts", region_name=self.region)
        service_id = client.meta.service_model.service_id

        signer = RequestSigner(service_id, session.region_name, 'sts', 'v4',
                               session.get_credentials(), session.events)

        params = {
            'method': self.METHOD,
            'url': 'https://' + self.STS_URL + '/?' + self.STS_ACTION,
            'body': {},
            'headers': {
                self.EKS_HEADER: self.cluster_id
            },
            'context': {}
        }

        signed_url = signer.generate_presigned_url(params,
                                                   region_name=self.region,
                                                   expires_in=self.EXPIRES,
                                                   operation_name='')
        return self.EKS_PREFIX + re.sub(
            r'=*', '',
            base64.urlsafe_b64encode(
                signed_url.encode('utf-8')).decode('utf-8'))
예제 #2
0
def get_bearer_token(cluster_id, region):
    STS_TOKEN_EXPIRES_IN = 3600
    session = boto3.session.Session()

    client = session.client('sts', region_name=region)
    service_id = client.meta.service_model.service_id

    signer = RequestSigner(service_id, region, 'sts', 'v4',
                           session.get_credentials(), session.events)

    params = {
        'method':
        'GET',
        'url':
        'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'
        .format(region),
        'body': {},
        'headers': {
            'x-k8s-aws-id': cluster_id
        },
        'context': {}
    }

    signed_url = signer.generate_presigned_url(params,
                                               region_name=region,
                                               expires_in=STS_TOKEN_EXPIRES_IN,
                                               operation_name='')

    base64_url = base64.urlsafe_b64encode(
        signed_url.encode('utf-8')).decode('utf-8')

    # remove any base64 encoding padding:
    return 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)
예제 #3
0
    def fetch_access_token_for_cluster(self, eks_cluster_name: str) -> str:
        session = self.get_session()
        service_id = self.conn.meta.service_model.service_id
        sts_url = (
            f'https://sts.{session.region_name}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'
        )

        signer = RequestSigner(
            service_id=service_id,
            region_name=session.region_name,
            signing_name='sts',
            signature_version='v4',
            credentials=session.get_credentials(),
            event_emitter=session.events,
        )

        request_params = {
            'method': 'GET',
            'url': sts_url,
            'body': {},
            'headers': {'x-k8s-aws-id': eks_cluster_name},
            'context': {},
        }

        signed_url = signer.generate_presigned_url(
            request_dict=request_params,
            region_name=session.region_name,
            expires_in=STS_TOKEN_EXPIRES_IN,
            operation_name='',
        )

        base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8')

        # remove any base64 encoding padding:
        return 'k8s-aws-v1.' + base64_url.rstrip("=")
예제 #4
0
    def get_token(self):
        """
        Return bearer token
        """
        sess = self.__get_session()
        signer = RequestSigner('sts', sess.region_name, 'sts', 'v4',
                               sess.get_credentials(), sess.events)

        params = {
            'method': self.METHOD,
            'url': 'https://' + self.STS_URL + '/?' + self.STS_ACTION,
            'body': {},
            'headers': {
                self.EKS_HEADER: self.cluster_id
            },
            'context': {}
        }

        signed_url = signer.generate_presigned_url(
            params,
            region_name=sess.region_name,
            expires_in=self.EXPIRES,
            operation_name='')

        return (self.EKS_PREFIX + base64.urlsafe_b64encode(
            signed_url.encode('utf-8')).decode('utf-8'))
def get_token():

    session = get_aws_session()

    sts_client = session.client("sts", region_name=REGION)
    print("caller identity ***####*************" +
          str(sts_client.get_caller_identity()))
    service_id = sts_client.meta.service_model.service_id
    print("service id ######" + service_id)
    signer = RequestSigner(service_id, session.region_name, 'sts', 'v4',
                           session.get_credentials(), session.events)

    params = {
        'method': 'GET',
        'url': 'https://' + STS_END_POINT + '/?' + STS_ACTION,
        'body': {},
        'headers': {
            EKS_HEADER: CLUSTER_NAME
        },
        'context': {}
    }

    signed_url = signer.generate_presigned_url(params,
                                               region_name=session.region_name,
                                               expires_in=EXPIRES_IN,
                                               operation_name='')
    print("signed url:  " + signed_url)

    return (
        EKS_PREFIX +
        base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8'))
예제 #6
0
    def _get_presigned_url(self, cluster_name, role_arn):
        session = self._session_handler.get_session(self._region_name,
                                                    role_arn)

        if self._region_name is None:
            self._region_name = session.get_config_variable('region')

        loader = botocore.loaders.create_loader()
        data = loader.load_data("endpoints")
        endpoint_resolver = botocore.regions.EndpointResolver(data)
        endpoint = endpoint_resolver.construct_endpoint(
            AUTH_SERVICE, self._region_name)
        signer = RequestSigner(ServiceId(AUTH_SERVICE), self._region_name,
                               AUTH_SERVICE, AUTH_SIGNING_VERSION,
                               session.get_credentials(),
                               session.get_component('event_emitter'))
        action_params = 'Action=' + AUTH_COMMAND + '&Version=' + AUTH_API_VERSION
        params = {
            'method': 'GET',
            'url': 'https://' + endpoint["hostname"] + '/?' + action_params,
            'body': {},
            'headers': {
                CLUSTER_NAME_HEADER: cluster_name
            },
            'context': {}
        }

        url = signer.generate_presigned_url(
            params,
            region_name=endpoint["credentialScope"]["region"],
            operation_name='',
            expires_in=URL_TIMEOUT)
        return url
예제 #7
0
    def get_auth_token(self):
        presign_expires = 60

        sts_http_action = 'Action=GetCallerIdentity&Version=2011-06-15'
        sts_http_method = 'GET'

        eks_header = 'x-k8s-aws-id'
        eks_prefix = 'k8s-aws-v1.'

        if self.role_arn:
            session = NewIdentity(role_arn=self.role_arn).get_session()
        else:
            session = boto3.session.Session()

        client = session.client("sts",region_name="us-east-1")
        service_id = client.meta.service_model.service_id

        signer = RequestSigner(
            service_id,
            session.region_name,
            'sts',
            'v4',
            session.get_credentials(),
            session.events
        )

        params = {
            'method': sts_http_method,
            'url': 'https://' + "sts.amazonaws.com" + '/?' + sts_http_action,
            'body': {},
            'headers': {
                eks_header: self.cluster_name
            },
            'context': {}
        }

        signed_url = signer.generate_presigned_url(
            params,
            region_name="us-east-1",
            expires_in=presign_expires,
            operation_name = ''
        )
        logger.debug("Pre-signed URL: {}".format(signed_url))
        logger.info("Caller Identity {}".format(client.get_caller_identity()))
        # This \/ \/ rstrip wasted 3 hours until I looked at aws cli code.
        return (
                eks_prefix +
                base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8').rstrip('=')
        )
예제 #8
0
def generate_aws_eks_bearer_token(cluster_name, challenge):
    """Function to generate the AWS EKS bearer Token

    Arguments:
        cluster_name {string} -- Cluster name for which the object is generated
        challenge {Object} -- Challenge Object

    Returns:
        {string} -- Generated bearer token
    """
    challenge_pk = challenge.id
    aws_keys = get_aws_credentials_for_challenge(challenge_pk)
    session = boto3.Session(
        aws_access_key_id=aws_keys["AWS_ACCESS_KEY_ID"],
        aws_secret_access_key=aws_keys["AWS_SECRET_ACCESS_KEY"],
    )
    region = aws_keys["AWS_REGION"]
    client = session.client("sts", region_name=region)
    service_id = client.meta.service_model.service_id
    signer = RequestSigner(
        service_id,
        region,
        "sts",
        "v4",
        session.get_credentials(),
        session.events,
    )
    params = {
        "method":
        "GET",
        "url":
        "https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15"
        .format(region),
        "body": {},
        "headers": {
            "x-k8s-aws-id": cluster_name
        },
        "context": {},
    }
    signed_url = signer.generate_presigned_url(params,
                                               region_name=region,
                                               expires_in=60,
                                               operation_name="")
    base64_url = base64.urlsafe_b64encode(
        signed_url.encode("utf-8")).decode("utf-8")
    # remove any base64 encoding padding
    bearer_token = "k8s-aws-v1." + re.sub(r"=*", "", base64_url)
    return bearer_token
예제 #9
0
def get_bearer_token(cluster, region):
    """Creates the authentication to token required by AWS IAM Authenticator. This is
    done by creating a base64 encoded string which represents a HTTP call to the STS
    GetCallerIdentity Query Request (https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html).
    The AWS IAM Authenticator decodes the base64 string and makes the request on behalf of the user.
    """
    STS_TOKEN_EXPIRES_IN = 60
    session = boto3.session.Session()

    client = session.client('sts', region_name=region)
    service_id = client.meta.service_model.service_id

    signer = RequestSigner(
        service_id,
        region,
        'sts',
        'v4',
        session.get_credentials(),
        session.events
    )

    params = {
        'method': 'GET',
        'url': 'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'.format(region),
        'body': {},
        'headers': {
            'x-k8s-aws-id': cluster
        },
        'context': {}
    }

    signed_url = signer.generate_presigned_url(
        params,
        region_name=region,
        expires_in=STS_TOKEN_EXPIRES_IN,
        operation_name=''
    )

    base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8')

    # need to remove base64 encoding padding:
    # https://github.com/kubernetes-sigs/aws-iam-authenticator/issues/202
    return 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)
예제 #10
0
def get_bearer_token(cluster, region):
    """Creates the authentication to token required by AWS IAM Authenticator. This is
    done by creating a base64 encoded string which represents a HTTP call to the STS
    GetCallerIdentity Query Request
    (https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html).
    The AWS IAM Authenticator decodes the base64 string and makes the request on behalf of the user.
    """
    STS_TOKEN_EXPIRES_IN = 60
    session = boto3.session.Session()

    client = session.client("sts", region_name=region)
    service_id = client.meta.service_model.service_id

    signer = RequestSigner(service_id, region, "sts", "v4",
                           session.get_credentials(), session.events)

    params = {
        "method":
        "GET",
        "url":
        "https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15"
        .format(region),
        "body": {},
        "headers": {
            "x-k8s-aws-id": cluster
        },
        "context": {},
    }

    signed_url = signer.generate_presigned_url(params,
                                               region_name=region,
                                               expires_in=STS_TOKEN_EXPIRES_IN,
                                               operation_name="")

    base64_url = base64.urlsafe_b64encode(
        signed_url.encode("utf-8")).decode("utf-8")

    # need to remove base64 encoding padding:
    # https://github.com/kubernetes-sigs/aws-iam-authenticator/issues/202
    return "k8s-aws-v1." + re.sub(r"=*", "", base64_url)
예제 #11
0
파일: get_token.py 프로젝트: aws/aws-cli
    def _get_presigned_url(self, cluster_name, role_arn):
        session = self._session_handler.get_session(
            self._region_name,
            role_arn
        )

        if self._region_name is None:
            self._region_name = session.get_config_variable('region')

        loader = botocore.loaders.create_loader()
        data = loader.load_data("endpoints")
        endpoint_resolver = botocore.regions.EndpointResolver(data)
        endpoint = endpoint_resolver.construct_endpoint(
            AUTH_SERVICE,
            self._region_name
        )
        signer = RequestSigner(
            ServiceId(AUTH_SERVICE),
            self._region_name,
            AUTH_SERVICE,
            AUTH_SIGNING_VERSION,
            session.get_credentials(),
            session.get_component('event_emitter')
        )
        action_params='Action=' + AUTH_COMMAND + '&Version=' + AUTH_API_VERSION
        params = {
            'method': 'GET',
            'url': 'https://' + endpoint["hostname"] + '/?' + action_params,
            'body': {},
            'headers': {CLUSTER_NAME_HEADER: cluster_name},
            'context': {}
        }

        url=signer.generate_presigned_url(
            params,
            region_name=endpoint["credentialScope"]["region"],
            operation_name='',
            expires_in=URL_TIMEOUT
        )
        return url
예제 #12
0
def get_token(cluster_id):
    """
    Return bearer token
    """
    session = boto3.session.Session()
    #Get ServiceID required by class RequestSigner
    client = session.client("sts", region_name=AWS_REGION)
    service_id = client.meta.service_model.service_id

    signer = RequestSigner(service_id, session.region_name, 'sts', 'v4',
                           session.get_credentials(), session.events)

    params = {
        'method':
        'GET',
        'url':
        'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'
        .format(AWS_REGION),
        'body': {},
        'headers': {
            'x-k8s-aws-id': cluster_id
        },
        'context': {}
    }

    # print("params: "+str(params))

    signed_url = signer.generate_presigned_url(params,
                                               region_name=AWS_REGION,
                                               expires_in=60,
                                               operation_name='')
    # print("SIGNED_URL: "+signed_url)

    base64_url = base64.urlsafe_b64encode(
        signed_url.encode('utf-8')).decode('utf-8')
    token = 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)
    # print("token: "+token)
    return token
예제 #13
0
    def _get_eks_bearer_token(self, cluster_id, region):
        session = boto3.session.Session(
            aws_access_key_id=self._aws_access_key_id,
            aws_secret_access_key=self._aws_secret_access_key,
        )

        client = session.client("sts", region_name=region)
        service_id = client.meta.service_model.service_id

        signer = RequestSigner(service_id, region, "sts", "v4",
                               session.get_credentials(), session.events)

        params = {
            "method":
            "GET",
            "url":
            "https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&"
            "Version=2011-06-15".format(region),
            "body": {},
            "headers": {
                "x-k8s-aws-id": cluster_id
            },
            "context": {},
        }

        signed_url = signer.generate_presigned_url(
            params,
            region_name=region,
            expires_in=self.STS_TOKEN_EXPIRES_IN,
            operation_name="",
        )

        base64_url = base64.urlsafe_b64encode(
            signed_url.encode("utf-8")).decode("utf-8")

        # remove any base64 encoding padding:
        return "Bearer k8s-aws-v1." + re.sub(r"=*", "", base64_url)
예제 #14
0
    def get_token(self):

        session = boto3.session.Session()

        #Get ServiceID required by class RequestSigner
        client = session.client("sts", region_name=self.region)
        service_id = client.meta.service_model.service_id

        #An object to sign requests before they go out over the wire using one of the authentication mechanisms defined in auth.py
        signer = RequestSigner(service_id, session.region_name, 'sts', 'v4',
                               session.get_credentials(), session.events)

        #creating the get request template
        params = {
            'method': self.METHOD,
            'url': 'https://' + self.STS_URL + '/?' + self.STS_ACTION,
            'body': {},
            'headers': {
                self.EKS_HEADER: self.cluster_id
            },
            'context': {}
        }

        #Generates a presigned url
        signed_url = signer.generate_presigned_url(
            params,
            region_name=session.region_name,
            expires_in=self.EXPIRES,
            operation_name='')

        #bearere token hash
        base64_url = base64.urlsafe_b64encode(
            signed_url.encode('utf-8')).decode('utf-8')

        #removed padding from beare token
        #return bearere token hash
        return self.EKS_PREFIX + re.sub(r'=*', '', base64_url)
예제 #15
0
class TestSigner(BaseSignerTest):

    def test_region_name(self):
        self.assertEqual(self.signer.region_name, 'region_name')

    def test_signature_version(self):
        self.assertEqual(self.signer.signature_version, 'v4')

    def test_signing_name(self):
        self.assertEqual(self.signer.signing_name, 'signing_name')

    def test_region_required_for_sigv4(self):
        self.signer = RequestSigner(
            'service_name', None, 'signing_name', 'v4', self.credentials,
            self.emitter)

        with self.assertRaises(NoRegionError):
            self.signer.sign('operation_name', mock.Mock())

    def test_get_auth(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth('service_name', 'region_name')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.fixed_credentials,
                service_name='service_name',
                region_name='region_name')

    def test_get_auth_signature_override(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-custom': auth_cls}):
            auth = self.signer.get_auth(
                'service_name', 'region_name', signature_version='v4-custom')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.fixed_credentials,
                service_name='service_name',
                region_name='region_name')

    def test_get_auth_bad_override(self):
        with self.assertRaises(UnknownSignatureVersionError):
            self.signer.get_auth('service_name', 'region_name',
                                 signature_version='bad')

    def test_emits_choose_signer(self):
        request = mock.Mock()

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', request)

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4')

    def test_choose_signer_override(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth.REQUIRES_REGION = False
        self.emitter.emit_until_response.return_value = (None, 'custom')

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'custom': auth}):
            self.signer.sign('operation_name', request)

        auth.assert_called_with(credentials=self.fixed_credentials)
        auth.return_value.add_auth.assert_called_with(request)

    def test_emits_before_sign(self):
        request = mock.Mock()

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', request)

        self.emitter.emit.assert_called_with(
            'before-sign.service_name.operation_name',
            request=mock.ANY, signing_name='signing_name',
            region_name='region_name', signature_version='v4',
            request_signer=self.signer)

    def test_disable_signing(self):
        # Returning botocore.UNSIGNED from choose-signer disables signing!
        request = mock.Mock()
        auth = mock.Mock()
        self.emitter.emit_until_response.return_value = (None,
                                                         botocore.UNSIGNED)

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth}):
            self.signer.sign('operation_name', request)

        auth.assert_not_called()

    def test_generate_url_emits_choose_signer(self):
        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.generate_presigned_url(request_dict, 'operation_name')

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4-query')

    def test_generate_url_choose_signer_override(self):
        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        auth = mock.Mock()
        auth.REQUIRES_REGION = False
        self.emitter.emit_until_response.return_value = (None, 'custom')

        auth_types_map = {'custom': mock.Mock(), 'custom-query': auth}
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types_map):
            self.signer.generate_presigned_url(request_dict, 'operation_name')

        auth.assert_called_with(credentials=self.fixed_credentials,
                                expires=3600)

    def test_generate_url_unsigned(self):
        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        self.emitter.emit_until_response.return_value = (
            None, botocore.UNSIGNED)

        url = self.signer.generate_presigned_url(
            request_dict, 'operation_name')

        self.assertEqual(url, 'https://foo.com')

    def test_generate_presigned_url(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name')
        auth.assert_called_with(
            credentials=self.fixed_credentials, region_name='region_name',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_region_override(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name',
                region_name='us-west-2')
        auth.assert_called_with(
            credentials=self.fixed_credentials, region_name='us-west-2',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_exipres_in(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name', expires_in=900)
        auth.assert_called_with(
            credentials=self.fixed_credentials,
            region_name='region_name',
            expires=900, service_name='signing_name')
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_presigned_url_throws_unsupported_signature_error(self):
        request_dict = {
            'headers': {},
            'url': 'https://s3.amazonaws.com/mybucket/myobject',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            'foo', self.credentials, self.emitter)
        with self.assertRaises(UnsupportedSignatureVersionError):
            self.signer.generate_presigned_url(
                request_dict, operation_name='foo')

    def test_signer_with_refreshable_credentials_gets_credential_set(self):
        class FakeCredentials(Credentials):
            def get_frozen_credentials(self):
                return ReadOnlyCredentials('foo', 'bar', 'baz')
        self.credentials = FakeCredentials('a', 'b', 'c')

        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            'v4', self.credentials, self.emitter)

        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth('service_name', 'region_name')
            self.assertEqual(auth, auth_cls.return_value)
            # Note we're called with 'foo', 'bar', 'baz', and *not*
            # 'a', 'b', 'c'.
            auth_cls.assert_called_with(
                credentials=ReadOnlyCredentials('foo', 'bar', 'baz'),
                service_name='service_name',
                region_name='region_name')

    def test_no_credentials_case_is_forwarded_to_signer(self):
        # If no credentials are given to the RequestSigner, we should
        # forward that fact on to the Auth class and let them handle
        # the error (which they already do).
        self.credentials = None
        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            'v4', self.credentials, self.emitter)
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth_instance(
                'service_name', 'region_name', 'v4')
            auth_cls.assert_called_with(
                service_name='service_name',
                region_name='region_name',
                credentials=None,
            )

    def test_sign_with_signing_type_standard(self):
        auth = mock.Mock()
        post_auth = mock.Mock()
        query_auth = mock.Mock()
        request = mock.Mock()
        auth_types = {
            'v4-presign-post': post_auth,
            'v4-query': query_auth,
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', request,
                             signing_type='standard')
        self.assertFalse(post_auth.called)
        self.assertFalse(query_auth.called)
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name'
        )

    def test_sign_with_signing_type_presign_url(self):
        auth = mock.Mock()
        post_auth = mock.Mock()
        query_auth = mock.Mock()
        request = mock.Mock()
        auth_types = {
            'v4-presign-post': post_auth,
            'v4-query': query_auth,
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', request,
                             signing_type='presign-url')
        self.assertFalse(post_auth.called)
        self.assertFalse(auth.called)
        query_auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name'
        )

    def test_sign_with_signing_type_presign_post(self):
        auth = mock.Mock()
        post_auth = mock.Mock()
        query_auth = mock.Mock()
        request = mock.Mock()
        auth_types = {
            'v4-presign-post': post_auth,
            'v4-query': query_auth,
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', request,
                             signing_type='presign-post')
        self.assertFalse(auth.called)
        self.assertFalse(query_auth.called)
        post_auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name'
        )

    def test_sign_with_region_name(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', request, region_name='foo')
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='foo'
        )

    def test_sign_with_expires_in(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', request, expires_in=2)
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name',
            expires=2
        )

    def test_unknown_signer_raises_unknown_on_standard(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        self.emitter.emit_until_response.return_value = (None, 'custom')
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            with self.assertRaises(UnknownSignatureVersionError):
                self.signer.sign('operation_name', request,
                                 signing_type='standard')

    def test_unknown_signer_raises_unsupported_when_not_standard(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        self.emitter.emit_until_response.return_value = (None, 'custom')
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            with self.assertRaises(UnsupportedSignatureVersionError):
                self.signer.sign('operation_name', request,
                                 signing_type='presign-url')

            with self.assertRaises(UnsupportedSignatureVersionError):
                self.signer.sign('operation_name', request,
                                 signing_type='presign-post')
예제 #16
0
class TestSigner(BaseSignerTest):

    def test_region_name(self):
        self.assertEqual(self.signer.region_name, 'region_name')

    def test_signature_version(self):
        self.assertEqual(self.signer.signature_version, 'v4')

    def test_signing_name(self):
        self.assertEqual(self.signer.signing_name, 'signing_name')

    def test_region_required_for_sigv4(self):
        self.signer = RequestSigner(
            ServiceId('service_name'), None, 'signing_name', 'v4',
            self.credentials, self.emitter
        )

        with self.assertRaises(NoRegionError):
            self.signer.sign('operation_name', self.request)

    def test_get_auth(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth('service_name', 'region_name')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.fixed_credentials,
                service_name='service_name',
                region_name='region_name')

    def test_get_auth_signature_override(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-custom': auth_cls}):
            auth = self.signer.get_auth(
                'service_name', 'region_name', signature_version='v4-custom')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.fixed_credentials,
                service_name='service_name',
                region_name='region_name')

    def test_get_auth_bad_override(self):
        with self.assertRaises(UnknownSignatureVersionError):
            self.signer.get_auth('service_name', 'region_name',
                                 signature_version='bad')

    def test_emits_choose_signer(self):
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', self.request)

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4', context=mock.ANY)

    def test_choose_signer_override(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = False
        self.emitter.emit_until_response.return_value = (None, 'custom')

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'custom': auth}):
            self.signer.sign('operation_name', self.request)

        auth.assert_called_with(credentials=self.fixed_credentials)
        auth.return_value.add_auth.assert_called_with(self.request)

    def test_emits_before_sign(self):
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', self.request)

        self.emitter.emit.assert_called_with(
            'before-sign.service_name.operation_name',
            request=self.request, signing_name='signing_name',
            region_name='region_name', signature_version='v4',
            request_signer=self.signer, operation_name='operation_name')

    def test_disable_signing(self):
        # Returning botocore.UNSIGNED from choose-signer disables signing!
        auth = mock.Mock()
        self.emitter.emit_until_response.return_value = (None,
                                                         botocore.UNSIGNED)

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth}):
            self.signer.sign('operation_name', self.request)

        auth.assert_not_called()

    def test_generate_url_emits_choose_signer(self):
        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.generate_presigned_url(request_dict, 'operation_name')

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4-query', context=mock.ANY)

    def test_choose_signer_passes_context(self):
        self.request.context = {'foo': 'bar'}

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', self.request)

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4', context={'foo': 'bar'})

    def test_generate_url_choose_signer_override(self):
        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        auth = mock.Mock()
        auth.REQUIRES_REGION = False
        self.emitter.emit_until_response.return_value = (None, 'custom')

        auth_types_map = {'custom': mock.Mock(), 'custom-query': auth}
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types_map):
            self.signer.generate_presigned_url(request_dict, 'operation_name')

        auth.assert_called_with(credentials=self.fixed_credentials,
                                expires=3600)

    def test_generate_url_unsigned(self):
        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        self.emitter.emit_until_response.return_value = (
            None, botocore.UNSIGNED)

        url = self.signer.generate_presigned_url(
            request_dict, 'operation_name')

        self.assertEqual(url, 'https://foo.com')

    def test_generate_presigned_url(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name')
        auth.assert_called_with(
            credentials=self.fixed_credentials, region_name='region_name',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_region_override(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name',
                region_name='us-west-2')
        auth.assert_called_with(
            credentials=self.fixed_credentials, region_name='us-west-2',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_exipres_in(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name', expires_in=900)
        auth.assert_called_with(
            credentials=self.fixed_credentials,
            region_name='region_name',
            expires=900, service_name='signing_name')
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_presigned_url_throws_unsupported_signature_error(self):
        request_dict = {
            'headers': {},
            'url': 'https://s3.amazonaws.com/mybucket/myobject',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        self.signer = RequestSigner(
            ServiceId('service_name'), 'region_name', 'signing_name',
            'foo', self.credentials, self.emitter)
        with self.assertRaises(UnsupportedSignatureVersionError):
            self.signer.generate_presigned_url(
                request_dict, operation_name='foo')

    def test_signer_with_refreshable_credentials_gets_credential_set(self):
        class FakeCredentials(Credentials):
            def get_frozen_credentials(self):
                return ReadOnlyCredentials('foo', 'bar', 'baz')
        self.credentials = FakeCredentials('a', 'b', 'c')

        self.signer = RequestSigner(
            ServiceId('service_name'), 'region_name', 'signing_name',
            'v4', self.credentials, self.emitter)

        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth('service_name', 'region_name')
            self.assertEqual(auth, auth_cls.return_value)
            # Note we're called with 'foo', 'bar', 'baz', and *not*
            # 'a', 'b', 'c'.
            auth_cls.assert_called_with(
                credentials=ReadOnlyCredentials('foo', 'bar', 'baz'),
                service_name='service_name',
                region_name='region_name')

    def test_no_credentials_case_is_forwarded_to_signer(self):
        # If no credentials are given to the RequestSigner, we should
        # forward that fact on to the Auth class and let them handle
        # the error (which they already do).
        self.credentials = None
        self.signer = RequestSigner(
            ServiceId('service_name'), 'region_name', 'signing_name',
            'v4', self.credentials, self.emitter)
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth_instance(
                'service_name', 'region_name', 'v4')
            auth_cls.assert_called_with(
                service_name='service_name',
                region_name='region_name',
                credentials=None,
            )

    def test_sign_with_signing_type_standard(self):
        auth = mock.Mock()
        post_auth = mock.Mock()
        query_auth = mock.Mock()
        auth_types = {
            'v4-presign-post': post_auth,
            'v4-query': query_auth,
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request,
                             signing_type='standard')
        self.assertFalse(post_auth.called)
        self.assertFalse(query_auth.called)
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name'
        )

    def test_sign_with_signing_type_presign_url(self):
        auth = mock.Mock()
        post_auth = mock.Mock()
        query_auth = mock.Mock()
        auth_types = {
            'v4-presign-post': post_auth,
            'v4-query': query_auth,
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request,
                             signing_type='presign-url')
        self.assertFalse(post_auth.called)
        self.assertFalse(auth.called)
        query_auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name'
        )

    def test_sign_with_signing_type_presign_post(self):
        auth = mock.Mock()
        post_auth = mock.Mock()
        query_auth = mock.Mock()
        auth_types = {
            'v4-presign-post': post_auth,
            'v4-query': query_auth,
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request,
                             signing_type='presign-post')
        self.assertFalse(auth.called)
        self.assertFalse(query_auth.called)
        post_auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name'
        )

    def test_sign_with_region_name(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request, region_name='foo')
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='foo'
        )

    def test_sign_override_region_from_context(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        self.request.context = {'signing': {'region': 'my-override-region'}}
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request)
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='my-override-region'
        )

    def test_sign_with_region_name_overrides_context(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        self.request.context = {'signing': {'region': 'context-override'}}
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request,
                             region_name='param-override')
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='param-override'
        )

    def test_sign_with_expires_in(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request, expires_in=2)
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='signing_name',
            region_name='region_name',
            expires=2
        )

    def test_sign_with_custom_signing_name(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            self.signer.sign('operation_name', self.request,
                             signing_name='foo')
        auth.assert_called_with(
            credentials=ReadOnlyCredentials('key', 'secret', None),
            service_name='foo',
            region_name='region_name'
        )

    def test_presign_with_custom_signing_name(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET',
            'context': {}
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, operation_name='operation_name',
                signing_name='foo')
        auth.assert_called_with(
            credentials=self.fixed_credentials,
            region_name='region_name',
            expires=3600, service_name='foo')
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_unknown_signer_raises_unknown_on_standard(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        self.emitter.emit_until_response.return_value = (None, 'custom')
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            with self.assertRaises(UnknownSignatureVersionError):
                self.signer.sign('operation_name', self.request,
                                 signing_type='standard')

    def test_unknown_signer_raises_unsupported_when_not_standard(self):
        auth = mock.Mock()
        auth_types = {
            'v4': auth
        }
        self.emitter.emit_until_response.return_value = (None, 'custom')
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS, auth_types):
            with self.assertRaises(UnsupportedSignatureVersionError):
                self.signer.sign('operation_name', self.request,
                                 signing_type='presign-url')

            with self.assertRaises(UnsupportedSignatureVersionError):
                self.signer.sign('operation_name', self.request,
                                 signing_type='presign-post')
예제 #17
0
class TestSigner(BaseSignerTest):

    def test_region_name(self):
        self.assertEqual(self.signer.region_name, 'region_name')

    def test_signature_version(self):
        self.assertEqual(self.signer.signature_version, 'v4')

    def test_signing_name(self):
        self.assertEqual(self.signer.signing_name, 'signing_name')

    def test_region_required_for_sigv4(self):
        self.signer = RequestSigner(
            'service_name', None, 'signing_name', 'v4', self.credentials,
            self.emitter)

        with self.assertRaises(NoRegionError):
            self.signer.sign('operation_name', mock.Mock())

    def test_get_auth(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth('service_name', 'region_name')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.credentials, service_name='service_name',
                region_name='region_name')

    def test_get_auth_cached(self):
        def side_effect(*args, **kwargs):
            return mock.Mock()
        auth_cls = mock.Mock(side_effect=side_effect)
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth1 = self.signer.get_auth('service_name', 'region_name')
            auth2 = self.signer.get_auth('service_name', 'region_name')

        self.assertEqual(auth1, auth2)

    def test_get_auth_cached_expires(self):
        def side_effect(*args, **kwargs):
            return mock.Mock()
        auth_cls = mock.Mock(side_effect=side_effect)
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth1 = self.signer.get_auth('service_name', 'region_name',
                                         expires=60)
            auth2 = self.signer.get_auth('service_name', 'region_name',
                                         expires=90)

        self.assertNotEqual(auth1, auth2)

    def test_get_auth_signature_override(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-custom': auth_cls}):
            auth = self.signer.get_auth(
                'service_name', 'region_name', signature_version='v4-custom')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.credentials, service_name='service_name',
                region_name='region_name')

    def test_get_auth_bad_override(self):
        with self.assertRaises(UnknownSignatureVersionError):
            self.signer.get_auth('service_name', 'region_name',
                                 signature_version='bad')

    def test_emits_choose_signer(self):
        request = mock.Mock()

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', request)

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4')

    def test_choose_signer_override(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth.REQUIRES_REGION = False
        self.emitter.emit_until_response.return_value = (None, 'custom')

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'custom': auth}):
            self.signer.sign('operation_name', request)

        auth.assert_called_with(credentials=self.credentials)
        auth.return_value.add_auth.assert_called_with(request=request)

    def test_emits_before_sign(self):
        request = mock.Mock()

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', request)

        self.emitter.emit.assert_called_with(
            'before-sign.service_name.operation_name',
            request=mock.ANY, signing_name='signing_name',
            region_name='region_name', signature_version='v4',
            request_signer=self.signer)

    def test_disable_signing(self):
        # Returning botocore.UNSIGNED from choose-signer disables signing!
        request = mock.Mock()
        auth = mock.Mock()
        self.emitter.emit_until_response.return_value = (None,
                                                         botocore.UNSIGNED)

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth}):
            self.signer.sign('operation_name', request)

        auth.assert_not_called()

    def test_generate_presigned_url(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(request_dict)
        auth.assert_called_with(
            credentials=self.credentials, region_name='region_name',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_region_override(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, region_name='us-west-2')
        auth.assert_called_with(
            credentials=self.credentials, region_name='us-west-2',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_exipres_in(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, expires_in=900)
        auth.assert_called_with(
            credentials=self.credentials, region_name='region_name',
            expires=900, service_name='signing_name')
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_fixes_s3_host(self):
        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            's3', self.credentials, self.emitter)

        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://s3.amazonaws.com/mybucket/myobject',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'s3-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, expires_in=900)
        auth.assert_called_with(
            credentials=self.credentials, region_name='region_name',
            expires=900, service_name='signing_name')
        self.assertEqual(presigned_url,
                         'https://mybucket.s3.amazonaws.com/myobject')

    def test_presigned_url_throws_unsupported_signature_error(self):
        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            'foo', self.credentials, self.emitter)
        with self.assertRaises(UnsupportedSignatureVersionError):
            self.signer.generate_presigned_url({})
예제 #18
0
def alertingfunc(cluster_id, region):

    # define variables
    initialtime = ""

    STS_TOKEN_EXPIRES_IN = 60
    session = boto3.session.Session(profile_name='default')

    client = session.client('sts', region_name=region)
    c = client.get_caller_identity()

    service_id = client.meta.service_model.service_id

    signer = RequestSigner(service_id, region, 'sts', 'v4',
                           session.get_credentials(), session.events)

    params = {
        'method':
        'GET',
        'url':
        'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'
        .format(region),
        'body': {},
        'headers': {
            'x-k8s-aws-id': cluster_id
        },
        'context': {}
    }

    signed_url = signer.generate_presigned_url(params,
                                               region_name=region,
                                               expires_in=STS_TOKEN_EXPIRES_IN,
                                               operation_name='')

    base64_url = base64.urlsafe_b64encode(
        signed_url.encode('utf-8')).decode('utf-8')

    output = subprocess.check_output(
        "kubectl get event -A -o custom-columns=NAME:.metadata.name,REASON:.reason",
        shell=True)
    events = output.decode('utf-8').split()
    print(events)

    # alerting or notifications to email or SNS

    emaillist = ["*****@*****.**"]

    def send_email(event):
        for member in emaillist:
            sender = smtplib.SMTP('smtp.gmail.com', 587)
            sender.starttls()
            sender.login("sender_email_id", "sender_email_id_password")
            message = "Node-Pod alerting mechanism:" + event
            sender.sendmail("sender_email_id", dest, message)
            sender.quit()

    def sns_notification(event):
        sns = boto3.client('sns')
        response = sns.publish(
            TopicArn=
            'arn:aws:sns:us-west-2:031679903962:newproject-NewprojectTopic2D161F5E-7N7IKAKxxxx',  #add the topic arn 
            Message='Alert: pod or node broken',
        )
        #print(response)

    if os.path.getsize("events.txt") == 0:
        print("No previous data related to kubectl events recorded")
        initialoutput = subprocess.check_output(
            "kubectl get events -o custom-columns=Firstseen:.firstTimestamp --sort-by='.firstTimestamp'",
            shell=True)
        newevents = initialoutput.decode('utf-8').split()
        newevents.reverse()
        initialtime = str(newevents[0])
        with open('events.txt', 'w') as f:
            with redirect_stdout(f):
                print(newevents[0])
        f.close()
    else:
        files = open("events.txt", "r+")
        prevtime = str(files.read()).split()
        newtime = prevtime[0]
        #print(prevtime)

    newoutput = subprocess.check_output(
        "kubectl get events -o custom-columns=Firstseen:.firstTimestamp --sort-by='.firstTimestamp'",
        shell=True)
    newevents = newoutput.decode('utf-8').split()
    newevents.reverse()
    currenttime = str(newevents[0])
    #print(type(currenttime))
    #print(currenttime)
    if (initialtime == currenttime):
        with open('events.txt', 'w') as f:
            with redirect_stdout(f):
                print(newevents[0])
        f.close()
    elif (newtime == currenttime):
        sys.exit()
    else:
        with open('events.txt', 'w') as f:
            with redirect_stdout(f):
                print(newevents[0])
        f.close()

    for previous, current in zip(events, events[1:]):
        if current == "RemovingNode":
            event = "Alert: A node is getting removed from cluster:" + previous
            print(event)
            send_email(event)
            sns_notification(event)
            continue
        elif current == "NotNotReady":
            event = "Alert: One of the node is in Not Ready state:" + previous
            print(event)
            send_email(event)
            sns_notification(event)
            continue
        elif current == "FailedScheduling":
            event = "Alert: Pod is failed to schedule:" + previous
            print(event)
            #send_email(event)
            sns_notification(event)
            continue
        elif current == "Failed":
            event = "Alert: FailedToCreateContainer or FailedToStartContainer or FailedToPullImage:" + previous
            print(event)
            send_email(event)
            sns_notification(event)
            continue
        elif current == "Killing":
            event = "Alert: KillingContainer:" + previous
            print(event)
            send_email(event)
            sns_notification(event)
            continue
        elif current == "NodeNotSchedulable":
            event = "Alert: NodeNotSchedulable:" + previous
            print(event)
            send_email(event)
            sns_notification(event)
            continue
        else:
            None
    return 0
예제 #19
0
class TestSigner(BaseSignerTest):

    def test_region_name(self):
        self.assertEqual(self.signer.region_name, 'region_name')

    def test_signature_version(self):
        self.assertEqual(self.signer.signature_version, 'v4')

    def test_signing_name(self):
        self.assertEqual(self.signer.signing_name, 'signing_name')

    def test_region_required_for_sigv4(self):
        self.signer = RequestSigner(
            'service_name', None, 'signing_name', 'v4', self.credentials,
            self.emitter)

        with self.assertRaises(NoRegionError):
            self.signer.sign('operation_name', mock.Mock())

    def test_get_auth(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth = self.signer.get_auth('service_name', 'region_name')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.credentials, service_name='service_name',
                region_name='region_name')

    def test_get_auth_cached(self):
        def side_effect(*args, **kwargs):
            return mock.Mock()
        auth_cls = mock.Mock(side_effect=side_effect)
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth1 = self.signer.get_auth('service_name', 'region_name')
            auth2 = self.signer.get_auth('service_name', 'region_name')

        self.assertEqual(auth1, auth2)

    def test_get_auth_cached_expires(self):
        def side_effect(*args, **kwargs):
            return mock.Mock()
        auth_cls = mock.Mock(side_effect=side_effect)
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth_cls}):
            auth1 = self.signer.get_auth('service_name', 'region_name',
                                         expires=60)
            auth2 = self.signer.get_auth('service_name', 'region_name',
                                         expires=90)

        self.assertNotEqual(auth1, auth2)

    def test_get_auth_signature_override(self):
        auth_cls = mock.Mock()
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-custom': auth_cls}):
            auth = self.signer.get_auth(
                'service_name', 'region_name', signature_version='v4-custom')

            self.assertEqual(auth, auth_cls.return_value)
            auth_cls.assert_called_with(
                credentials=self.credentials, service_name='service_name',
                region_name='region_name')

    def test_get_auth_bad_override(self):
        with self.assertRaises(UnknownSignatureVersionError):
            self.signer.get_auth('service_name', 'region_name',
                                 signature_version='bad')

    def test_emits_choose_signer(self):
        request = mock.Mock()

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', request)

        self.emitter.emit_until_response.assert_called_with(
            'choose-signer.service_name.operation_name',
            signing_name='signing_name', region_name='region_name',
            signature_version='v4')

    def test_choose_signer_override(self):
        request = mock.Mock()
        auth = mock.Mock()
        auth.REQUIRES_REGION = False
        self.emitter.emit_until_response.return_value = (None, 'custom')

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'custom': auth}):
            self.signer.sign('operation_name', request)

        auth.assert_called_with(credentials=self.credentials)
        auth.return_value.add_auth.assert_called_with(request=request)

    def test_emits_before_sign(self):
        request = mock.Mock()

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': mock.Mock()}):
            self.signer.sign('operation_name', request)

        self.emitter.emit.assert_called_with(
            'before-sign.service_name.operation_name',
            request=mock.ANY, signing_name='signing_name',
            region_name='region_name', signature_version='v4',
            request_signer=self.signer)

    def test_disable_signing(self):
        # Returning botocore.UNSIGNED from choose-signer disables signing!
        request = mock.Mock()
        auth = mock.Mock()
        self.emitter.emit_until_response.return_value = (None,
                                                         botocore.UNSIGNED)

        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4': auth}):
            self.signer.sign('operation_name', request)

        auth.assert_not_called()

    def test_generate_presigned_url(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(request_dict)
        auth.assert_called_with(
            credentials=self.credentials, region_name='region_name',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_region_override(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, region_name='us-west-2')
        auth.assert_called_with(
            credentials=self.credentials, region_name='us-west-2',
            service_name='signing_name', expires=3600)
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_with_exipres_in(self):
        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://foo.com',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'v4-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, expires_in=900)
        auth.assert_called_with(
            credentials=self.credentials, region_name='region_name',
            expires=900, service_name='signing_name')
        self.assertEqual(presigned_url, 'https://foo.com')

    def test_generate_presigned_url_fixes_s3_host(self):
        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            's3', self.credentials, self.emitter)

        auth = mock.Mock()
        auth.REQUIRES_REGION = True

        request_dict = {
            'headers': {},
            'url': 'https://s3.amazonaws.com/mybucket/myobject',
            'body': b'',
            'url_path': '/',
            'method': 'GET'
        }
        with mock.patch.dict(botocore.auth.AUTH_TYPE_MAPS,
                             {'s3-query': auth}):
            presigned_url = self.signer.generate_presigned_url(
                request_dict, expires_in=900)
        auth.assert_called_with(
            credentials=self.credentials, region_name='region_name',
            expires=900, service_name='signing_name')
        self.assertEqual(presigned_url,
                         'https://mybucket.s3.amazonaws.com/myobject')

    def test_presigned_url_throws_unsupported_signature_error(self):
        self.signer = RequestSigner(
            'service_name', 'region_name', 'signing_name',
            'foo', self.credentials, self.emitter)
        with self.assertRaises(UnsupportedSignatureVersionError):
            self.signer.generate_presigned_url({})
예제 #20
0
    def create_client_config(self):
        config = kubernetes_client.Configuration()

        if self.auth_mode == "aws-iam":
            # https://github.com/kubernetes-sigs/aws-iam-authenticator
            # https://aws.amazon.com/de/about-aws/whats-new/2019/05/amazon-eks-simplifies-kubernetes-cluster-authentication/
            # https://github.com/aws/aws-cli/blob/develop/awscli/customizations/eks/get_token.py

            # get cluster info
            import boto3
            eks_client = boto3.client(
                'eks',
                region_name=self.aws_region_name,
                aws_access_key_id=self.aws_access_key_id,
                aws_secret_access_key=self.aws_secret_access_key)
            cluster_info = eks_client.describe_cluster(
                name=self.aws_cluster_name)
            aws_cluster_ca = cluster_info['cluster']['certificateAuthority'][
                'data']
            aws_cluster_url = cluster_info['cluster']['endpoint']

            # get authentication token
            from botocore.signers import RequestSigner  # pylint: disable=import-error
            STS_TOKEN_EXPIRES_IN = 60
            session = boto3.Session(
                region_name=self.aws_region_name,
                aws_access_key_id=self.aws_access_key_id,
                aws_secret_access_key=self.aws_secret_access_key)
            sts_client = session.client('sts')
            service_id = sts_client.meta.service_model.service_id
            token_signer = RequestSigner(service_id,
                                         self.aws_region_name, 'sts', 'v4',
                                         session.get_credentials(),
                                         session.events)
            signed_url = token_signer.generate_presigned_url(
                {
                    'method':
                    'GET',
                    'url':
                    'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'
                    .format(self.aws_region_name),
                    'body': {},
                    'headers': {
                        'x-k8s-aws-id': self.aws_cluster_name
                    },
                    'context': {}
                },
                region_name=self.aws_region_name,
                expires_in=STS_TOKEN_EXPIRES_IN,
                operation_name='')
            base64_url = base64.urlsafe_b64encode(
                signed_url.encode('utf-8')).decode('utf-8')
            auth_token = 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)

            config.host = aws_cluster_url
            ca_data = base64.standard_b64decode(aws_cluster_ca)
            fp = tempfile.NamedTemporaryFile(
                delete=False)  # TODO when to delete?
            fp.write(ca_data)
            fp.close()
            config.ssl_ca_cert = fp.name
            config.api_key["authorization"] = auth_token
            config.api_key_prefix["authorization"] = "Bearer"

        elif self.auth_mode == "cert-key":
            config.host = self.cluster_url

            if self.client_cert:
                try:
                    cert_data = base64.standard_b64decode(self.client_cert)
                    fp = tempfile.NamedTemporaryFile(
                        delete=False)  # TODO when to delete?
                    fp.write(cert_data)
                    fp.close()
                    config.cert_file = fp.name
                except Exception as e:
                    raise Exception("Error applying cluster cert: %s" % (e))

            if self.client_key:
                try:
                    key_data = base64.standard_b64decode(self.client_key)
                    fp = tempfile.NamedTemporaryFile(
                        delete=False)  # TODO when to delete?
                    fp.write(key_data)
                    fp.close()
                    config.key_file = fp.name
                except Exception as e:
                    raise Exception("Error applying cluster key: %s" % (e))

            if self.cluster_ca:
                try:
                    cluster_ca_data = base64.standard_b64decode(
                        self.cluster_ca)
                    fp = tempfile.NamedTemporaryFile(
                        delete=False)  # TODO when to delete?
                    fp.write(cluster_ca_data)
                    fp.close()
                    config.ssl_ca_cert = fp.name
                except Exception as e:
                    raise Exception("Error applying cluster ca: %s" % (e))

            config.verify_ssl = False

        elif self.auth_mode == "user-token":
            # TODO: should cluster_ca be used here too?
            config.host = self.cluster_url
            config.api_key["authorization"] = self.user_token
            config.api_key_prefix["authorization"] = "Bearer"
            config.verify_ssl = False

        elif self.auth_mode == "user-password":
            if self.cluster_ca:
                try:
                    cluster_ca_data = base64.standard_b64decode(
                        self.cluster_ca)
                    fp = tempfile.NamedTemporaryFile(
                        delete=False)  # TODO when to delete?
                    fp.write(cluster_ca_data)
                    fp.close()
                    config.ssl_ca_cert = fp.name
                except Exception as e:
                    raise Exception("Error applying cluster ca: %s" % (e))
            config.host = self.cluster_url

            import urllib3
            config.api_key["authorization"] = urllib3.util.make_headers(
                basic_auth=self.user_name + ':' +
                self.user_password).get('authorization')

            config.verify_ssl = False

        elif self.auth_mode == "in-cluster":
            kubernetes_config.load_incluster_config()
            config = kubernetes_client.Configuration._default

        else:
            raise Exception("invalid auth mode '%s'" % self.auth_mode)

        return config