def Initialize(config=None, external_hostname: Optional[Text] = None, admin_password: Optional[Text] = None, redownload_templates: bool = False, repack_templates: bool = True): """Initialize or update a GRR configuration.""" print("Checking write access on config %s" % config["Config.writeback"]) if not os.access(config.parser.filename, os.W_OK): raise IOError("Config not writeable (need sudo?)") print("\nStep 0: Importing Configuration from previous installation.") options_imported = 0 prev_config_file = config.Get("ConfigUpdater.old_config", default=None) if prev_config_file and os.access(prev_config_file, os.R_OK): print("Found config file %s." % prev_config_file) # pytype: disable=wrong-arg-count if input("Do you want to import this configuration? " "[yN]: ").upper() == "Y": options_imported = ImportConfig(prev_config_file, config) # pytype: enable=wrong-arg-count else: print("No old config file found.") print("\nStep 1: Setting Basic Configuration Parameters") print( "We are now going to configure the server using a bunch of questions.") fs_config = FleetspeakConfig() fs_config.Prompt(config) ConfigureDatastore(config) ConfigureUrls(config, external_hostname=external_hostname) ConfigureEmails(config) print("\nStep 2: Key Generation") if config.Get("PrivateKeys.server_key", default=None): if options_imported > 0: print( "Since you have imported keys from another installation in the " "last step,\nyou probably do not want to generate new keys now." ) # pytype: disable=wrong-arg-count if (input("You already have keys in your config, do you want to" " overwrite them? [yN]: ").upper() or "N") == "Y": config_updater_keys_util.GenerateKeys(config, overwrite_keys=True) # pytype: enable=wrong-arg-count else: config_updater_keys_util.GenerateKeys(config) fs_config.Write(config) FinalizeConfigInit(config, admin_password=admin_password, redownload_templates=redownload_templates, repack_templates=repack_templates, prompt=True)
def main(argv): del argv # Unused. if not flags.FLAGS.dest_server_config_path: raise ValueError("dest_server_config_path flag has to be provided.") if not flags.FLAGS.dest_client_config_path: raise ValueError("dest_client_config_path flag has to be provided.") admin_ui_port = portpicker.pick_unused_port() frontend_port = portpicker.pick_unused_port() source_server_config_path = package.ResourcePath( "grr-response-core", "install_data/etc/grr-server.yaml") config_lib.LoadConfig(config.CONFIG, source_server_config_path) config.CONFIG.SetWriteBack(flags.FLAGS.dest_server_config_path) # TODO(user): remove when AFF4 is gone. config.CONFIG.Set("Database.enabled", True) config.CONFIG.Set("Blobstore.implementation", "DbBlobStore") config.CONFIG.Set("Database.implementation", "MysqlDB") config.CONFIG.Set("Mysql.database", flags.FLAGS.config_mysql_database) if flags.FLAGS.config_mysql_username is not None: config.CONFIG.Set("Mysql.username", flags.FLAGS.config_mysql_username) if flags.FLAGS.config_mysql_password is not None: config.CONFIG.Set("Mysql.password", flags.FLAGS.config_mysql_password) config.CONFIG.Set("AdminUI.port", admin_ui_port) config.CONFIG.Set("AdminUI.headless", True) config.CONFIG.Set("Frontend.bind_address", "127.0.0.1") config.CONFIG.Set("Frontend.bind_port", frontend_port) config.CONFIG.Set("Server.initialized", True) config.CONFIG.Set("Cron.active", False) config.CONFIG.Set("Client.poll_max", 1) config.CONFIG.Set("Client.server_urls", ["http://localhost:%d/" % frontend_port]) if flags.FLAGS.config_logging_path is not None: config.CONFIG.Set("Logging.path", flags.FLAGS.config_logging_path) config.CONFIG.Set("Logging.verbose", False) if flags.FLAGS.config_osquery_path: config.CONFIG.Set("Osquery.path", flags.FLAGS.config_osquery_path) config_updater_keys_util.GenerateKeys(config.CONFIG) config.CONFIG.Write() config_lib.SetPlatformArchContext() context = list(config.CONFIG.context) context.append("Client Context") config_data = build_helpers.GetClientConfig(context, validate=False, deploy_timestamp=False) with io.open(flags.FLAGS.dest_client_config_path, "w") as fd: fd.write(config_data)
def main(argv): del argv # Unused. if not flags.FLAGS.dest_server_config_path: raise ValueError("dest_server_config_path flag has to be provided.") if not flags.FLAGS.dest_client_config_path: raise ValueError("dest_client_config_path flag has to be provided.") admin_ui_port = portpicker.pick_unused_port() frontend_port = portpicker.pick_unused_port() datastore_port = portpicker.pick_unused_port() source_server_config_path = package.ResourcePath( "grr-response-core", "install_data/etc/grr-server.yaml") config_lib.LoadConfig(config.CONFIG, source_server_config_path) config.CONFIG.SetWriteBack(flags.FLAGS.dest_server_config_path) # TODO(user): remove when AFF4 is gone. config.CONFIG.Set("Database.aff4_enabled", False) config.CONFIG.Set("Database.enabled", True) config.CONFIG.Set("Blobstore.implementation", "DbBlobStore") config.CONFIG.Set("Database.implementation", "SharedMemoryDB") config.CONFIG.Set("SharedMemoryDB.port", datastore_port) config.CONFIG.Set("AdminUI.port", admin_ui_port) config.CONFIG.Set("AdminUI.headless", True) config.CONFIG.Set("Frontend.bind_address", "127.0.0.1") config.CONFIG.Set("Frontend.bind_port", frontend_port) config.CONFIG.Set("Server.initialized", True) config.CONFIG.Set("Client.poll_max", 1) config.CONFIG.Set("Client.server_urls", ["http://localhost:%d/" % frontend_port]) config_updater_keys_util.GenerateKeys(config.CONFIG) config.CONFIG.Write() config_lib.SetPlatformArchContext() context = list(config.CONFIG.context) context.append("Client Context") deployer = build.ClientRepacker() config_data = deployer.GetClientConfig(context, validate=False, deploy_timestamp=False) with io.open(flags.FLAGS.dest_client_config_path, "w") as fd: fd.write(config_data)
def InitializeNoPrompt(config=None, token=None): """Initialize GRR with no prompts. Args: config: config object token: auth token Raises: ValueError: if required flags are not provided, or if the config has already been initialized. IOError: if config is not writeable ConfigInitError: if GRR is unable to connect to a running MySQL instance. This method does the minimum work necessary to configure GRR without any user prompting, relying heavily on config default values. User must supply the external hostname, admin password, and MySQL password; everything else is set automatically. """ if config["Server.initialized"]: raise ValueError("Config has already been initialized.") if not flags.FLAGS.external_hostname: raise ValueError( "--noprompt set, but --external_hostname was not provided.") if not flags.FLAGS.admin_password: raise ValueError( "--noprompt set, but --admin_password was not provided.") if flags.FLAGS.mysql_password is None: raise ValueError( "--noprompt set, but --mysql_password was not provided.") print("Checking write access on config %s" % config.parser) if not os.access(config.parser.filename, os.W_OK): raise IOError("Config not writeable (need sudo?)") config_dict = {} config_dict["Datastore.implementation"] = "MySQLAdvancedDataStore" config_dict["Mysql.host"] = (flags.FLAGS.mysql_hostname or config["Mysql.host"]) config_dict["Mysql.port"] = (flags.FLAGS.mysql_port or config["Mysql.port"]) config_dict["Mysql.database_name"] = (flags.FLAGS.mysql_db or config["Mysql.database_name"]) config_dict["Mysql.database_username"] = ( flags.FLAGS.mysql_username or config["Mysql.database_username"]) hostname = flags.FLAGS.external_hostname config_dict["Client.server_urls"] = [ "http://%s:%s/" % (hostname, config["Frontend.bind_port"]) ] config_dict["AdminUI.url"] = "http://%s:%s" % (hostname, config["AdminUI.port"]) config_dict["Logging.domain"] = hostname config_dict["Monitoring.alert_email"] = "grr-monitoring@%s" % hostname config_dict["Monitoring.emergency_access_email"] = ("grr-emergency@%s" % hostname) config_dict["Rekall.enabled"] = flags.FLAGS.enable_rekall # Print all configuration options, except for the MySQL password. print("Setting configuration as:\n\n%s" % config_dict) config_dict["Mysql.database_password"] = flags.FLAGS.mysql_password if CheckMySQLConnection(config_dict): print("Successfully connected to MySQL with the given configuration.") else: print( "Error: Could not connect to MySQL with the given configuration.") raise ConfigInitError() for key, value in iteritems(config_dict): config.Set(key, value) config_updater_keys_util.GenerateKeys(config) FinalizeConfigInit(config, token)
def main(args): """Main.""" grr_config.CONFIG.AddContext(contexts.COMMAND_LINE_CONTEXT) grr_config.CONFIG.AddContext(contexts.CONFIG_UPDATER_CONTEXT) if args.subparser_name == "initialize": config_lib.ParseConfigCommandLine() if args.noprompt: config_updater_util.InitializeNoPrompt( grr_config.CONFIG, external_hostname=args.external_hostname, admin_password=args.admin_password, mysql_hostname=args.mysql_hostname, mysql_port=args.mysql_port, mysql_username=args.mysql_username, mysql_password=args.mysql_password, mysql_db=args.mysql_db, mysql_client_key_path=args.mysql_client_key_path, mysql_client_cert_path=args.mysql_client_cert_path, mysql_ca_cert_path=args.mysql_ca_cert_path, redownload_templates=args.redownload_templates, repack_templates=not args.norepack_templates) else: config_updater_util.Initialize( grr_config.CONFIG, external_hostname=args.external_hostname, admin_password=args.admin_password, redownload_templates=args.redownload_templates, repack_templates=not args.norepack_templates) return server_startup.Init() try: print("Using configuration %s" % grr_config.CONFIG) except AttributeError: raise RuntimeError("No valid config specified.") if args.subparser_name == "generate_keys": try: config_updater_keys_util.GenerateKeys( grr_config.CONFIG, overwrite_keys=args.overwrite_keys) except RuntimeError as e: # GenerateKeys will raise if keys exist and overwrite_keys is not set. print("ERROR: %s" % e) sys.exit(1) grr_config.CONFIG.Write() elif args.subparser_name == "repack_clients": upload = not args.noupload repacking.TemplateRepacker().RepackAllTemplates(upload=upload) elif args.subparser_name == "show_user": if args.username: print(config_updater_util.GetUserSummary(args.username)) else: print(config_updater_util.GetAllUserSummaries()) elif args.subparser_name == "update_user": config_updater_util.UpdateUser(args.username, password=args.password, is_admin=args.admin) elif args.subparser_name == "delete_user": config_updater_util.DeleteUser(args.username) elif args.subparser_name == "add_user": config_updater_util.CreateUser(args.username, password=args.password, is_admin=args.admin) elif args.subparser_name == "upload_python": config_updater_util.UploadSignedBinary( args.file, rdf_objects.SignedBinaryID.BinaryType.PYTHON_HACK, args.platform, upload_subdirectory=args.upload_subdirectory) elif args.subparser_name == "upload_exe": config_updater_util.UploadSignedBinary( args.file, rdf_objects.SignedBinaryID.BinaryType.EXECUTABLE, args.platform, upload_subdirectory=args.upload_subdirectory) elif args.subparser_name == "set_var": var = args.var val = args.val config = grr_config.CONFIG print("Setting %s to %s" % (var, val)) if val.startswith("["): # Allow setting of basic lists. val = val[1:-1].split(",") config.Set(var, val) config.Write() elif args.subparser_name == "switch_datastore": config_updater_util.SwitchToRelDB(grr_config.CONFIG) grr_config.CONFIG.Write() elif args.subparser_name == "upload_artifact": with io.open(args.file, "r") as filedesc: source = filedesc.read() try: artifact.UploadArtifactYamlFile(source, overwrite=args.overwrite_artifact) except rdf_artifacts.ArtifactDefinitionError as e: print("Error %s. You may need to set --overwrite_artifact." % e) elif args.subparser_name == "delete_artifacts": artifact_list = args.artifact if not artifact_list: raise ValueError("No artifact to delete given.") artifact_registry.DeleteArtifactsFromDatastore(artifact_list) print("Artifacts %s deleted." % artifact_list) elif args.subparser_name == "rotate_server_key": print(""" You are about to rotate the server key. Note that: - Clients might experience intermittent connection problems after the server keys rotated. - It's not possible to go back to an earlier key. Clients that see a new certificate will remember the cert's serial number and refuse to accept any certificate with a smaller serial number from that point on. """) if input("Continue? [yN]: ").upper() == "Y": if args.keylength: keylength = int(args.keylength) else: keylength = grr_config.CONFIG["Server.rsa_key_length"] maintenance_utils.RotateServerKey(cn=args.common_name, keylength=keylength)
def InitializeNoPrompt(config=None, external_hostname = None, admin_password = None, mysql_hostname = None, mysql_port = None, mysql_username = None, mysql_password = None, mysql_db = None, mysql_client_key_path = None, mysql_client_cert_path = None, mysql_ca_cert_path = None, redownload_templates = False, repack_templates = True): """Initialize GRR with no prompts. Args: config: config object external_hostname: A hostname. admin_password: A password used for the admin user. mysql_hostname: A hostname used for establishing connection to MySQL. mysql_port: A port used for establishing connection to MySQL. mysql_username: A username used for establishing connection to MySQL. mysql_password: A password used for establishing connection to MySQL. mysql_db: Name of the MySQL database to use. mysql_client_key_path: The path name of the client private key file. mysql_client_cert_path: The path name of the client public key certificate. mysql_ca_cert_path: The path name of the CA certificate file. redownload_templates: Indicates whether templates should be re-downloaded. repack_templates: Indicates whether templates should be re-packed. Raises: ValueError: if required flags are not provided, or if the config has already been initialized. IOError: if config is not writeable ConfigInitError: if GRR is unable to connect to a running MySQL instance. This method does the minimum work necessary to configure GRR without any user prompting, relying heavily on config default values. User must supply the external hostname, admin password, and MySQL password; everything else is set automatically. """ if config["Server.initialized"]: raise ValueError("Config has already been initialized.") if not external_hostname: raise ValueError( "--noprompt set, but --external_hostname was not provided.") if not admin_password: raise ValueError("--noprompt set, but --admin_password was not provided.") if mysql_password is None: raise ValueError("--noprompt set, but --mysql_password was not provided.") print("Checking write access on config %s" % config.parser) if not os.access(config.parser.filename, os.W_OK): raise IOError("Config not writeable (need sudo?)") config_dict = {} config_dict["Database.implementation"] = "MysqlDB" config_dict["Blobstore.implementation"] = "DbBlobStore" config_dict["Mysql.host"] = mysql_hostname or config["Mysql.host"] config_dict["Mysql.port"] = mysql_port or config["Mysql.port"] config_dict["Mysql.database_name"] = config_dict[ "Mysql.database"] = mysql_db or config["Mysql.database_name"] config_dict["Mysql.database_username"] = config_dict["Mysql.username"] = ( mysql_username or config["Mysql.database_username"]) config_dict["Client.server_urls"] = [ "http://%s:%s/" % (external_hostname, config["Frontend.bind_port"]) ] config_dict["AdminUI.url"] = "http://%s:%s" % (external_hostname, config["AdminUI.port"]) config_dict["Logging.domain"] = external_hostname config_dict["Monitoring.alert_email"] = ("grr-monitoring@%s" % external_hostname) config_dict["Monitoring.emergency_access_email"] = ("grr-emergency@%s" % external_hostname) # Print all configuration options, except for the MySQL password. print("Setting configuration as:\n\n%s" % config_dict) config_dict["Mysql.database_password"] = config_dict[ "Mysql.password"] = mysql_password if mysql_client_key_path is not None: config_dict["Mysql.client_key_path"] = mysql_client_key_path config_dict["Mysql.client_cert_path"] = mysql_client_cert_path config_dict["Mysql.ca_cert_path"] = mysql_ca_cert_path if CheckMySQLConnection(config_dict): print("Successfully connected to MySQL with the given configuration.") else: print("Error: Could not connect to MySQL with the given configuration.") raise ConfigInitError() for key, value in iteritems(config_dict): config.Set(key, value) config_updater_keys_util.GenerateKeys(config) FinalizeConfigInit( config, admin_password=admin_password, redownload_templates=redownload_templates, repack_templates=repack_templates, prompt=False)
def main(argv): """Main.""" del argv # Unused. if flags.FLAGS.subparser_name == "version": version = config_server.VERSION["packageversion"] print("GRR configuration updater {}".format(version)) return token = config_updater_util.GetToken() grr_config.CONFIG.AddContext(contexts.COMMAND_LINE_CONTEXT) grr_config.CONFIG.AddContext(contexts.CONFIG_UPDATER_CONTEXT) if flags.FLAGS.subparser_name == "initialize": config_lib.ParseConfigCommandLine() if flags.FLAGS.noprompt: config_updater_util.InitializeNoPrompt(grr_config.CONFIG, token=token) else: config_updater_util.Initialize(grr_config.CONFIG, token=token) return server_startup.Init() try: print("Using configuration %s" % grr_config.CONFIG) except AttributeError: raise RuntimeError("No valid config specified.") if flags.FLAGS.subparser_name == "generate_keys": try: config_updater_keys_util.GenerateKeys( grr_config.CONFIG, overwrite_keys=flags.FLAGS.overwrite_keys) except RuntimeError as e: # GenerateKeys will raise if keys exist and overwrite_keys is not set. print("ERROR: %s" % e) sys.exit(1) grr_config.CONFIG.Write() elif flags.FLAGS.subparser_name == "repack_clients": upload = not flags.FLAGS.noupload repacking.TemplateRepacker().RepackAllTemplates(upload=upload, token=token) elif flags.FLAGS.subparser_name == "show_user": if flags.FLAGS.username: print(config_updater_util.GetUserSummary(flags.FLAGS.username)) else: print(config_updater_util.GetAllUserSummaries()) elif flags.FLAGS.subparser_name == "update_user": config_updater_util.UpdateUser(flags.FLAGS.username, password=flags.FLAGS.password, is_admin=flags.FLAGS.admin) elif flags.FLAGS.subparser_name == "delete_user": config_updater_util.DeleteUser(flags.FLAGS.username) elif flags.FLAGS.subparser_name == "add_user": config_updater_util.CreateUser(flags.FLAGS.username, password=flags.FLAGS.password, is_admin=flags.FLAGS.admin) elif flags.FLAGS.subparser_name == "upload_python": config_updater_util.UploadSignedBinary( flags.FLAGS.file, rdf_objects.SignedBinaryID.BinaryType.PYTHON_HACK, flags.FLAGS.platform, upload_subdirectory=flags.FLAGS.upload_subdirectory, token=token) elif flags.FLAGS.subparser_name == "upload_exe": config_updater_util.UploadSignedBinary( flags.FLAGS.file, rdf_objects.SignedBinaryID.BinaryType.EXECUTABLE, flags.FLAGS.platform, upload_subdirectory=flags.FLAGS.upload_subdirectory, token=token) elif flags.FLAGS.subparser_name == "set_var": config = grr_config.CONFIG print("Setting %s to %s" % (flags.FLAGS.var, flags.FLAGS.val)) if flags.FLAGS.val.startswith("["): # Allow setting of basic lists. flags.FLAGS.val = flags.FLAGS.val[1:-1].split(",") config.Set(flags.FLAGS.var, flags.FLAGS.val) config.Write() elif flags.FLAGS.subparser_name == "upload_artifact": yaml.load(open(flags.FLAGS.file, "rb")) # Check it will parse. try: artifact.UploadArtifactYamlFile( open(flags.FLAGS.file, "rb").read(), overwrite=flags.FLAGS.overwrite_artifact) except rdf_artifacts.ArtifactDefinitionError as e: print("Error %s. You may need to set --overwrite_artifact." % e) elif flags.FLAGS.subparser_name == "delete_artifacts": artifact_list = flags.FLAGS.artifact if not artifact_list: raise ValueError("No artifact to delete given.") artifact_registry.DeleteArtifactsFromDatastore(artifact_list, token=token) print("Artifacts %s deleted." % artifact_list) elif flags.FLAGS.subparser_name == "download_missing_rekall_profiles": print("Downloading missing Rekall profiles.") s = rekall_profile_server.GRRRekallProfileServer() s.GetMissingProfiles() elif flags.FLAGS.subparser_name == "rotate_server_key": print(""" You are about to rotate the server key. Note that: - Clients might experience intermittent connection problems after the server keys rotated. - It's not possible to go back to an earlier key. Clients that see a new certificate will remember the cert's serial number and refuse to accept any certificate with a smaller serial number from that point on. """) if builtins.input("Continue? [yN]: ").upper() == "Y": if flags.FLAGS.keylength: keylength = int(flags.FLAGS.keylength) else: keylength = grr_config.CONFIG["Server.rsa_key_length"] maintenance_utils.RotateServerKey(cn=flags.FLAGS.common_name, keylength=keylength)