Beispiel #1
0
def pair_device(auth_code, user_auth_credentials, device_encryption_info, encryption_context, server_name="",
                server_app_id = "",
                config=SplunkConfig()):
    """
    Part 2/2 of the registration process.
    Send splunk app's public key information and encrypted credentials for user to cloudgateway. Upon success, this
    will complete the credential swap as now the client has the splunk app's credentials and the splunk app has received
    the app's public key

    :param auth_code:  auth code of the device
    :param user_auth_credentials: UserAuthCredentials object interface which captures different forms of session tokens
    :param device_encryption_info: DeviceInfo object which was returned in the authenticate_code api call
    :param encryption_context: EncryptionContext object. Can be a regular EncryptionContext or a subclass such
    as SplunkEncryptionContext depending on whether you want to run in standalone mode or not.
    :param server_name: optional parameter for name of server so that device can identify which instance it is paired
    with
    :param config: CloudgatewaySdkConfig object
    :return:
    """
    user_auth_credentials.validate()
    sodium_client = encryption_context.sodium_client

    encrypt_public_key = encryption_context.encrypt_public_key()
    sign_public_key = encryption_context.sign_public_key()
    encryption_func = partial(encrypt_for_send, sodium_client, device_encryption_info.encrypt_public_key)
    auth_header = sb_auth_header(encryption_context)

    session_token = user_auth_credentials.get_credentials() if sys.version_info < (3, 0) else str.encode(user_auth_credentials.get_credentials())
    encrypted_session_token = encryption_context.secure_session_token(session_token)
    encrypted_credentials_bundle = build_encypted_credentials_bundle(user_auth_credentials.get_username(),
                                                                     encrypted_session_token, encryption_func,
                                                                     server_app_id,
                                                                     deployment_name=server_name)
    pair_device_with_sb(auth_code, auth_header, device_encryption_info.device_id, encrypt_public_key, sign_public_key,
                        encrypted_credentials_bundle, config)
def send_public_key_to_spacebridge(websocket_protocol, config=SplunkConfig()):
    """ Send the splapp public signing key to spacebridge
        Abstraction layer for the spacebrige request. This function:
        1. Signs the splapp public signing key with the splapp private signing key
        2. Creates a proto request with the public signing key and the signature
        3. Sends the proto request to spacebridge
        :param websocket_protocol: The websocket protocol
        :param config: The configuration used to make the request
    """

    websocket_protocol.logger.debug('Starting sending splapp public key to spacebridge')
    encryption_context = websocket_protocol.encryption_context
    sign_func = partial(sign_detached,
                        encryption_context.sodium_client,
                        encryption_context.sign_private_key()
                       )
    public_signing_key = encryption_context.sign_public_key()
    request_proto = http_pb2.RegisterSigningPublicKeyRequest()
    request_proto.publicKeyForSigning = public_signing_key
    request_proto.signature = sign_func(public_signing_key)
    serialized_proto = request_proto.SerializeToString()
    headers = {'Content-Type': 'application/x-protobuf',
               'Authorization': str(sb_auth_header(encryption_context))}
    client = AsyncClient()
    yield send_key(headers, serialized_proto, config, client, websocket_protocol)
    websocket_protocol.logger.debug('Finished send_key method. No logs after start message indicate success.')
Beispiel #3
0
def make_device_authentication_request(device_info, encryption_context, config):
    """Makes a device authentication request to Cloud Gateway. If successful,
    Cloud Gateway will return a DeviceAuthenticationResponse object.
    
    Args:
        device_info ([DeviceInfo]): device info object containing client's
            public keys
        encryption_context ([EncryptionContext]):
    
    Raises:
        RestException.CloudgatewayServerError
    
    Returns:
        [Requests.Response]: response object whose content is a serialized 
            DeviceAuthenticationResponse proto
    """
    request_proto = build_device_authentication_request(device_info)
    try:
        spacebridge_header = {'Authorization': sb_auth_header(encryption_context)}
        return requests.post(sb_client_auth_endpoint(config),
                            headers=spacebridge_header,
                            data=request_proto.SerializeToString(),
                            )

    except Exception as e:
        raise RestException.CloudgatewayServerError('Unable to reach cloudgateway: {0}'.format(e), 503)
Beispiel #4
0
    def send(self, device_id, payload, request_id=None):
        """Send a message to a particular device using Cloud Gateway
        Args:
            device_id ([binary]): id of the device to send the message to
            payload ([string]): Message to be sent. Can be any format you want (json, serialized proto, etc.)
            request_id (str, optional): [description]. Defaults to "123".

        Returns:
            [requests.response]: response returned by requests object
        """
        if not request_id:
            request_id = ServerResponse.create_rid()

        send_message_request = http_pb2.SendMessageRequest()
        recipient_info = self.message_handler.fetch_device_info(device_id)

        build_encrypted_payload(
            recipient_info,
            self.encryption_context,
            payload,
            request_id,
            self.logger,
            signed_envelope=send_message_request.signedEnvelope)

        # self.connector.factory.protocol.sendMessage(send_message_request.SerializeToString())

        spacebridge_header = {
            'Authorization': sb_auth_header(self.encryption_context)
        }

        with requests_ssl_context(self.key_bundle) as cert:
            return requests.post(sb_message_endpoint(self.config),
                                 headers=spacebridge_header,
                                 data=send_message_request.SerializeToString(),
                                 cert=cert.name)
Beispiel #5
0
def make_authentication_result_request(auth_code,
                                       encryption_context,
                                       config,
                                       key_bundle=None):
    """ Make AuthenticationResultRequest to Cloud Gateway

    Args:
        auth_code ([string]): 10-digit auth code returned by Cloud Gateway on Device Authentication Request
        encryption_context ([EncryptionContext]):

    Raises:
        RestException.CloudgatewayServerError:

    Returns:
        [Requests.Response]: Response object containing serialized AuthenticationResultResponse object
    """
    request_proto = build_authentication_result_request(auth_code)
    with requests_ssl_context(key_bundle) as cert:
        try:
            spacebridge_header = {
                'Authorization': sb_auth_header(encryption_context)
            }
            return requests.get(sb_client_auth_result_endpoint(
                auth_code, config),
                                headers=spacebridge_header,
                                data=request_proto.SerializeToString(),
                                cert=cert.name)

        except Exception as e:
            raise RestException.CloudgatewayServerError(
                'Unable to reach cloudgateway: {0}'.format(e), 503)
Beispiel #6
0
def async_send_confirmation_result(confirmation_result, encryption_context, async_sb_client):
    """

    Send an async http request to spacebridge to complete MDM registration

    Args:
        confirmation_result (MdmAuthenticationConfirmationResult)
        encryption_context (EncryptionContext)
        async_sb_client (AsyncSpacebridgeClient):
    """

    return async_sb_client.async_send_request(
      api='/api/mdm/confirm',
      auth_header=None,
      data=confirmation_result.SerializeToString(),
      headers={'Content-Type': 'application/x-protobuf', 'Authorization': sb_auth_header(encryption_context)}
    )
Beispiel #7
0
def submit_auth_code(auth_code, encryption_context, config):
    """
    Given an auth code, submit it to cloudgateway's auth endpoint. Raise an exception if cannot reach cloudgateway
    :param auth_code
    :param encryption_context
    :return: seriealized protobuf response from cloudgateway
    """
    try:
        spacebridge_header = {
            'Authorization': sb_auth_header(encryption_context)
        }
        return requests.get(sb_auth_endpoint(auth_code, config),
                            headers=spacebridge_header,
                            proxies=config.get_proxies())
    except Exception as e:
        raise RestException.CloudgatewayServerError(
            'Unable to reach cloudgateway: {0}'.format(e), 503)
Beispiel #8
0
def unregister_device(device_id, encryption_context, config=SplunkConfig()):
    """
    Unregister ascljk a device from cloud gateway. Initiating this will cause cloud gateway to remove the routing entry
    and also force the client device to unregister

    :param device_id:  device id from DeviceInfo object
    :param encryption_context: EncryptionContext object. Can be a regular EncryptionContext or a subclass such
    as SplunkEncryptionContext depending on whether you want to run in standalone mode or not. 
    :return: DeviceUnregistrationResponse proto or throws an exception if the request can't be completed
    :param config: CloudgatewaySdkConfig object
    """

    unregister_proto = unregister.build_device_unregister_req(device_id, encryption_context)
    raw_response = unregister.make_unregister_req(unregister_proto, sb_auth_header(encryption_context), config)
    unregister.parse_sb_response(raw_response)

    return raw_response
Beispiel #9
0
    def build_client_factory(self):
        """
        Setup a cloudgatewayclientfactory object before a connection is established to Cloudgateway. Configures
        things like the uri to connect on, auth headers, websocket protocol options, etc.

        Returns: CloudgatewayClientFactory object

        """

        headers = {'Authorization': sb_auth_header(self.encryption_context)}

        if self.shard_id:
            headers[constants.HEADER_SHARD_ID] = self.shard_id
            self.logger.info("Using shard_id={}".format(self.shard_id))

        ws_url = "wss://{0}/deployment".format(
            self.config.get_spacebridge_server())
        proxy, auth = self.config.get_ws_https_proxy_settings()

        if auth:
            headers['Proxy-Authorization'] = 'Basic ' + auth

        if sys.version_info < (3, 0):
            factory = cloudgateway_client_protocol.CloudgatewayClientFactory(
                ws_url, headers=headers, proxy=proxy)
            factory.configure(
                cloudgateway_client_protocol.SpacebridgeWebsocketProtocol,
                self.max_reconnect_delay)
            factory.setProtocolOptions(autoFragmentSize=65536)

        else:
            factory = WebSocketClientFactory(ws_url, headers=headers)
            factory.protocol = aio_client_protocol.AioSpacebridgeServerProtocol
            factory.autoFragmentSize = 65536

        factory.protocol.encryption_context = self.encryption_context
        factory.protocol.system_auth_header = SplunkAuthHeader(
            self.system_session_key)
        factory.protocol.parent_process_monitor = self.parent_process_monitor
        factory.protocol.logger = self.logger
        factory.protocol.mode = self.mode
        factory.protocol.cluster_monitor = self.cluster_monitor
        factory.protocol.websocket_context = self.websocket_context
        return factory
Beispiel #10
0
def submit_auth_code(auth_code, encryption_context, config, key_bundle=None):
    """
    Given an auth code, submit it to cloudgateway's auth endpoint. Raise an exception if cannot reach cloudgateway
    :param auth_code
    :param encryption_context
    :param mtls_pkcs12: A PKCS12 object containing the certificate and private key information for mTLS
    :return: seriealized protobuf response from cloudgateway
    """

    with requests_ssl_context(key_bundle) as cert:
        try:
            spacebridge_header = {'Authorization': sb_auth_header(encryption_context)}
            return requests.get(sb_auth_endpoint(auth_code, config),
                                headers=spacebridge_header,
                                proxies=config.get_proxies(),
                                cert=cert.name
                                )
        except Exception as e:
            raise RestException.CloudgatewayServerError('Unable to reach cloudgateway: {0}'.format(e), 503)
Beispiel #11
0
def make_mdm_authentication_request(username, password, server_info, encryption_context, mdm_sign_private_key, config):
    """ Make AuthenticationResultRequest to Cloud Gateway

    Args:
        auth_code ([string]): 10-digit auth code returned by Cloud Gateway on Device Authentication Request
        encryption_context ([EncryptionContext]):

    Raises:
        RestException.CloudgatewayServerError:

    Returns:
        [Requests.Response]: Response object containing serialized AuthenticationResultResponse object
    """
    request_proto = build_mdm_authentication_request(username, password, encryption_context, server_info,
                                                     mdm_sign_private_key)
    try:
        return requests.post(
            url='{0}/api/mdm/authenticate'.format(config.get_spacebridge_domain()),
            headers={'Content-Type': 'application/x-protobuf', 'Authorization': sb_auth_header(encryption_context)},
            data=request_proto.SerializeToString(),
            proxies=config.get_proxies()
        )
    except Exception as e:
        raise RestException.CloudgatewayServerError('Unable to reach cloudgateway: {0}'.format(e), 503)