def __init__( self, api_id: Optional[str] = None, api_secret: Optional[str] = None, url: Optional[str] = DEFAULT_URL, **kwargs, ): CensysAPIBase.__init__(self, url, **kwargs) # Gets config file config = get_config() # Try to get credentials self._api_id = (api_id or os.getenv("CENSYS_API_ID") or config.get(DEFAULT, "api_id")) self._api_secret = (api_secret or os.getenv("CENSYS_API_SECRET") or config.get(DEFAULT, "api_secret")) if not self._api_id or not self._api_secret: raise CensysException("No API ID or API secret configured.") self._session.auth = (self._api_id, self._api_secret) # Generate concrete paths to be called self.search_path = f"search/{self.INDEX_NAME}" self.view_path = f"view/{self.INDEX_NAME}" self.report_path = f"report/{self.INDEX_NAME}" # Confirm setup self.account()
def __init__(self, api_key: Optional[str] = None, **kwargs): url = kwargs.pop("url", self.DEFAULT_URL) CensysAPIBase.__init__(self, url=url, **kwargs) # Gets config file config = get_config() # Try to get credentials self._api_key = (api_key or os.getenv("CENSYS_ASM_API_KEY") or config.get(DEFAULT, "asm_api_key")) if not self._api_key: raise CensysMissingApiKeyException("No ASM API key configured.") self._session.headers.update({ "Content-Type": "application/json", "Censys-Api-Key": self._api_key })
def cli_config(_): # pragma: no cover """ config subcommand. Args: _: Argparse Namespace. """ api_id_prompt = "Censys API ID" api_secret_prompt = "Censys API Secret" config = get_config() api_id = config.get(DEFAULT, "api_id") api_secret = config.get(DEFAULT, "api_secret") if api_id and api_secret: redacted_id = api_id.replace(api_id[:32], 32 * "*") redacted_secret = api_secret.replace(api_secret[:28], 28 * "*") api_id_prompt = f"{api_id_prompt} [{redacted_id}]" api_secret_prompt = f"{api_secret_prompt} [{redacted_secret}]" api_id = input(api_id_prompt + ": ").strip() or api_id api_secret = input(api_secret_prompt + ": ").strip() or api_secret if not (api_id and api_secret): print("Please enter valid credentials") sys.exit(1) try: client = CensysSearchAPI(api_id, api_secret) account = client.account() email = account.get("email") # Assumes that login was successfully config.set(DEFAULT, "api_id", api_id) config.set(DEFAULT, "api_secret", api_secret) write_config(config) print(f"\nSuccessfully authenticated for {email}") sys.exit(0) except CensysUnauthorizedException: print("Failed to authenticate") sys.exit(1)
def __init__(self, api_id: Optional[str] = None, api_secret: Optional[str] = None, **kwargs): # Gets config file config = get_config() # Try to get credentials self._api_id = (api_id or os.getenv("CENSYS_API_ID") or config.get(DEFAULT, "api_id")) self._api_secret = (api_secret or os.getenv("CENSYS_API_SECRET") or config.get(DEFAULT, "api_secret")) if not self._api_id or not self._api_secret: raise CensysException("No API ID or API secret configured.") self.timeout = kwargs.get("timeout") or self.DEFAULT_TIMEOUT self._api_url = (kwargs.get("url") or os.getenv("CENSYS_API_URL") or self.DEFAULT_URL) # Create a session and sets credentials self._session = requests.Session() proxies = kwargs.get("proxies") if proxies: if "http" in proxies.keys(): warnings.warn("HTTP proxies will not be used.") proxies.pop("http", None) self._session.proxies = proxies self._session.auth = (self._api_id, self._api_secret) self._session.headers.update({ "accept": "application/json, */8", "User-Agent": " ".join([ requests.utils.default_user_agent(), kwargs.get("user_agent") or kwargs.get("user_agent_identifier") or self.DEFAULT_USER_AGENT, ]), }) # Confirm setup self.account()
def __init__( self, api_id: Optional[str] = None, api_secret: Optional[str] = None, url: Optional[str] = None, timeout: Optional[int] = None, user_agent_identifier: Optional[str] = None, ): # Gets config file config = get_config() # Try to get credentials self.api_id = (api_id or os.getenv("CENSYS_API_ID") or config.get(DEFAULT, "api_id")) self.api_secret = (api_secret or os.getenv("CENSYS_API_SECRET") or config.get(DEFAULT, "api_secret")) if not self.api_id or not self.api_secret: raise CensysException("No API ID or API secret configured.") self.timeout = timeout or self.DEFAULT_TIMEOUT self._api_url = url or os.getenv("CENSYS_API_URL") or self.DEFAULT_URL # Create a session and sets credentials self._session = requests.Session() self._session.auth = (self.api_id, self.api_secret) self._session.headers.update({ "accept": "application/json, */8", "User-Agent": " ".join([ requests.utils.default_user_agent(), user_agent_identifier or self.DEFAULT_USER_AGENT, ]), }) # Confirm setup self.account()
def cli_asm_config(_): # pragma: no cover """ config asm subcommand. Args: _: Argparse Namespace. """ api_key_prompt = "Censys ASM API Key" config = get_config() api_key = config.get(DEFAULT, "asm_api_key") if api_key: key_len = len(api_key) - 4 redacted_api_key = api_key.replace(api_key[:key_len], key_len * "*") api_key_prompt = f"{api_key_prompt} [{redacted_api_key}]" api_key = input(api_key_prompt + ": ").strip() or api_key if not api_key: print("Please enter valid credentials") sys.exit(1) try: AsmClient(api_key) # Assumes that login was successfully config.set(DEFAULT, "asm_api_key", api_key) write_config(config) print("\nSuccessfully authenticated") sys.exit(0) except CensysUnauthorizedException: print("Failed to authenticate") sys.exit(1)
def get_parser() -> argparse.ArgumentParser: """ Gets ArgumentParser for CLI. Returns: argparse.ArgumentParser """ config = get_config() auth = argparse.ArgumentParser(add_help=False) auth.add_argument( "--api-id", default=os.getenv("CENSYS_API_ID") or config.get(DEFAULT, "api_id"), required=False, help="a Censys API ID \ (alternatively you can use the env variable CENSYS_API_ID)", ) auth.add_argument( "--api-secret", default=os.getenv("CENSYS_API_SECRET") or config.get(DEFAULT, "api_secret"), required=False, help="a Censys API SECRET \ (alternatively you can use the env variable CENSYS_API_SECRET)", ) parser = argparse.ArgumentParser() parser.set_defaults() subparsers = parser.add_subparsers() # Search Specific Args search_parser = subparsers.add_parser( "search", description="Query Censys Search for resource data by providing a query \ string, the resource index, and the fields to be returned", help="query Censys search", parents=[auth], ) search_parser.add_argument( "-q", "--query", type=str, required=True, help="a string written in Censys Search syntax", ) index_types = ["ipv4", "certs", "websites"] index_metavar = "ipv4|certs|websites" index_default = "ipv4" search_parser.add_argument( "--index-type", type=str, default=index_default, choices=index_types, metavar=index_metavar, help="which resource index to query", ) # Backwards compatibility search_parser.add_argument( "--query_type", type=str, default=index_default, choices=index_types, metavar=index_metavar, help=argparse.SUPPRESS, ) search_parser.add_argument("--fields", nargs="+", help="list of index-specific fields") search_parser.add_argument( "--overwrite", action="store_true", default=False, help="overwrite instead of append fields returned by default \ with fields provided in the fields argument", ) search_parser.add_argument( "-f", "--format", type=str, default="screen", metavar="json|csv|screen", help="format of output", ) search_parser.add_argument( "-o", "--output", type=Path, help="output file path", ) search_parser.add_argument("--start-page", default=1, type=int, help="page number to start from") search_parser.add_argument( "--max-pages", default=1, type=int, help="maximum number of pages of results to return", ) search_parser.set_defaults(func=search) # HNRI Specific Args hnri_parser = subparsers.add_parser( "hnri", description="Home Network Risk Identifier (H.N.R.I.)", help="home network risk identifier", parents=[auth], ) hnri_parser.set_defaults(func=hnri) # Config Specific Args config_parser = subparsers.add_parser( "config", description="Configure Censys Search API Settings", help="configure Censys search API settings", ) config_parser.set_defaults(func=cli_config) # ASM Config Args asm_config_parser = subparsers.add_parser( "config-asm", description="Configure Censys ASM API Settings", help="configure Censys ASM API settings", ) asm_config_parser.set_defaults(func=cli_asm_config) return parser
import os import unittest import pytest from censys.config import DEFAULT, get_config config = get_config() api_key = config.get(DEFAULT, "asm_api_key") or os.getenv("CENSYS_ASM_API_KEY") required_env_asm = pytest.mark.skipif( not api_key, reason="API key not found", ) RESOURCE_PAGING_RESULTS = ["a", "b", "c", "a", "b", "c", "a", "b", "c"] TEST_TIMEOUT = 30 TEST_SUCCESS_CODE = 200 BASE_URL = "https://app.censys.io/api/v1" @required_env_asm class CensysAsmTestCase(unittest.TestCase): pass class MockResponse: # Dummy resource list to iterate over for testing paging RESOURCES = ["a", "b", "c"] # Dummy end of events list to simulate 3 pages of results END_OF_EVENTS = [False, False, True]
def test_write_default(self, mock_file): get_config() os.path.isdir.assert_called_with(censys_path) os.mkdir.assert_called_with(censys_path) os.path.exists.assert_called_with(test_config_path) mock_file.assert_called_with(test_config_path, "w")