예제 #1
0
    def setup(self, dest=''):
        '''
        CLI Setup
        '''
        try:
            # Set Parent Parser
            log.debug("Setting up argparser")
            self.parser = argparse.ArgumentParser(
                description=self.description,
                formatter_class=self.formatter_class)
            log.debug("Parent parser set")
            # Add parent subparser
            parent_subparser = self._add_subparser(
                self.parser,
                title='Commands',
                help_text='usage: rainmaker_admin_cli.py {command} -h for '
                'additional help',
                dest=dest)
            return parent_subparser

        except KeyError as key_err:
            log.error(KeyError(str(key_err)))
            print(traceback.format_exc())
        except AttributeError as attr_err:
            log.error(AttributeError(str(attr_err)))
            print(traceback.format_exc())
        except Exception as err:
            log.error(
                CLIError('ERROR: Error occurred during '
                         'CLI Setup. {}'.format(err)))
            print(traceback.format_exc())
        return
예제 #2
0
def configure_server(vars=None):
    '''
    Set Server Config

    :param vars: `endpoint` as key - Endpoint of server to use
    :type vars: str

    :raises Exception: If there is any exception while configuring server
            KeyboardInterrupt: If there is a keyboard interrupt by user

    :return: None on Failure
    :rtype: None
    '''
    try:
        log.debug("Configure server")
        ret_status = _cli_arg_check(vars['endpoint'], '--endpoint <endpoint>')
        if not ret_status:
            return

        config = configmanager.Config(config="server")
        ret_status = config.set_server_config(vars['endpoint'])
        if not ret_status:
            log.error("Failed to save server config")
            return
        else:
            log.info("Saved new server config")

        log.info('You can now run: \npython rainmaker_admin_cli.py account '
                 'login -h (Login)')
    except KeyboardInterrupt:
        log.error("\nServer config not set")
    except Exception as e:
        log.error("Error: {}".format(e))
예제 #3
0
    def save_config(self, data):
        '''
        Save login config data to file

        :param data: Login data to be set
        :type data: dict
        '''
        try:
            log.debug("Saving login config data")
            if not os.path.isdir(CONFIG_DIRECTORY):
                log.info('Config directory does not exist, '
                         'creating new directory : {}'.format(
                             CONFIG_DIRECTORY))
                os.makedirs(CONFIG_DIRECTORY)

            login_cfg_data = self._set_login_config_data(data)
            if not login_cfg_data:
                return False, False

            with open(self.config_file, 'w+', encoding='utf-8') as cfg_file:
                cfg_file.write(str(json.dumps(login_cfg_data)))

            return True, self.config_file

        except Exception as save_config_err:
            log.error(save_config_err)
            return False, False
예제 #4
0
def generate_cacert(cacert_info, ca_private_key):
    '''
    Generate CA Certificate

    :param cacert_info: CA certificate info
    :type cacert_info: dict

    :param ca_private_key: CA Private Key
    :type ca_private_key: RSA Private Key
    '''
    try:
        log.info("\nGenerating CA Certificate")
        ca_public_key = ca_private_key.public_key()
        subj_name_list = _create_subj_name_list(cacert_info)
        if not subj_name_list:
            return False
        issuer_name = [
            x509.NameAttribute(NameOID.COMMON_NAME, cacert_info['common_name'])
        ]
        ca_cert = _generate_cert(subject_name=subj_name_list,
                                 issuer_name=issuer_name,
                                 public_key=ca_public_key,
                                 ca_key=ca_private_key,
                                 ca=True)
        if not ca_cert:
            return False
        return ca_cert
    except Exception as err:
        log.debug("Error: {} . Cannot create CA Certificate".format(err))
예제 #5
0
def _get_cacert_user_input(cfg, cfg_menu):
    '''
    Get CA Certficate Data from User

    :param cfg: CA Certificate config
    :type cfg: dict

    :param cfg_menu: CA Certificate config menu
    :type cfg_menu: dict

    :return: Config data
    :rtype: dict
    '''
    # Get CA Certificate data input from user
    log.debug("Getting CA certificate config data from User")

    for (cfg_key, _) in iteritems(cfg):
        log.debug("Config Key: {}".format(cfg_key))
        while True:
            input_data = input(cfg_menu[cfg_key])
            log.debug("Input received from user: {}".format(input_data))
            if input_data:
                if cfg_key == "country_name" and not len(input_data) == 2:
                    print("Country name must be a 2 character country code")
                    continue
                cfg[cfg_key] = str(input_data)
                log.debug("Config: {} set for key: {}".format(
                    input_data, cfg_key))
            elif not input_data and cfg_key == "common_name":
                print("Common Name is mandatory")
                continue
            break
    log.debug("CA Certificate config data received from user")
    return cfg
예제 #6
0
def download_from_url(request_url):
    '''
    Download file from url

    :param request_url: Request URL to download file from
    :type request_url: str
    '''
    try:
        response = None
        while True:
            try:
                log.debug("Downloading file from url: {}".format(request_url))
                response = requests.get(url=request_url)
                response.raise_for_status()
            except requests.exceptions.SSLError:
                raise(SSLError())
            except (ConnectionError):
                log.error(NetworkError())
            except RequestException as err:
                log.error(err)

            if response:
                log.info("Node ids file downloaded successfully")
                log.debug("Response content: {}".format(response.content))
                return response.content
            else:
                log.info("Retrying...")
                time.sleep(5)

    except Exception as err:
        raise Exception(err)
예제 #7
0
def _extra_config_files_checks(outdir, extra_config, extra_values, file_id):
    log.debug("Extra config file checks")
    set_to_false = None
    if extra_config and not extra_values:
        log.info('ADDITIONAL_VALUES file must also be provided in config '
                 'alongwith ADDITIONAL_CONFIG file.')
        set_to_false = False
    if file_id and file_id in ['node_id']:
        log.info('`node_id` is the default fileid. '
                 'Any new fileid provided as input must be a key in the '
                 'ADDITIONAL_VALUES file provided in config.')
        set_to_false = False
    if file_id and file_id not in ['node_id'] and not extra_values:
        log.info(
            'Fileid provided must have corresponding values in ADDITIONAL_VALUES file in config. '
            'Please provide ADDITIONAL_VALUES file in config.')
        set_to_false = False
    '''
    if extra_values and file_id and file_id not in ['node_id'] and not extra_config:
        log.info('Fileid provided must be a config key. Please provide ADDITIONAL_CONFIG file '
                    'alongwith ADDITIONAL_VALUES file in config.')
        set_to_false = False
    '''
    if extra_config or extra_values:
        log.debug("Verifying mfg files input")
        # Verify mfg files
        verify_mfg_files(outdir, extra_config, extra_values, file_id)
    if set_to_false is False:
        return False
    return True
예제 #8
0
def generate_csr(private_key, common_name):
    '''
    Generate CSR

    :param private_key: Private Key
    :type private_key: RSA Private Key

    :param common_name: Common Name
    :type common_name: str
    '''
    try:
        log.debug("Generate CSR")
        # Generate CSR on host
        csr_builder = x509.CertificateSigningRequestBuilder()
        csr_builder = csr_builder.subject_name(
            x509.Name([
                x509.NameAttribute(NameOID.COMMON_NAME, common_name),
            ]))

        csr_builder = csr_builder.add_extension(
            x509.BasicConstraints(ca=False, path_length=None),
            critical=True,
        )
        csr = csr_builder.sign(private_key, hashes.SHA256(), default_backend())
        if not isinstance(csr, x509.CertificateSigningRequest):
            print('CSR Type Is Wrong, '
                  'expected x509.CertificateSigningRequest')
            return False
        return csr
    except Exception as err:
        raise Exception(err)
예제 #9
0
 def __init__(self, dest_config_filename, dest_values_filename, data,
              outdir, keygen, file_id):
     self.conf = dest_config_filename
     self.values = dest_values_filename
     if data:
         self.size = data['BINARY_SIZE']
     else:
         self.size = data
     self.outdir = outdir
     # Set version=2, multipage blob support enabled
     self.version = 2
     self.keygen = keygen
     self.inputkey = None
     # These must be None, there must be no input from user for these params
     self.keyfile = None
     self.input = None
     self.output = None
     self.fileid = file_id
     log.debug('Arguments set to send to manufacturing tool for '
               'creating NVS partiton binaries')
     log.debug('conf: {}, values: {}, size: {}, '
               'outdir: {}, version: {} '
               'keygen: {}, inputkey: {}, keyfile: {}, '
               'input: {}, output: {}, fileid: {}'.format(
                   self.conf, self.values, self.size, self.outdir,
                   self.version, self.keygen, self.inputkey, self.keyfile,
                   self.input, self.output, self.fileid))
예제 #10
0
    def _add_subparser(self, parser, cmd="", title="", help_text="", dest=""):
        '''
        Add subparser

        :param parser: Parent parser to set command for
        :type parser: <Argparse parser>

        :param cmd: CLI Command
        :type cmd: str

        :param title: CLI Command title
        :type title: str

        :param help_text: CLI Command help text
        :type help_text: str
        '''
        log.debug("Adding subparser for cmd: {}".format(cmd))

        # Add subparser to parser
        if title or help_text:
            subparser = parser.add_subparsers(title=title,
                                              help=help_text,
                                              dest=dest)
        else:
            subparser = parser.add_subparsers(dest=dest)
        return subparser
예제 #11
0
def get_fileid_val(file_identifier, keys_in_config_file, keys_in_values_file,
                   values_data_line, key_value_data, fileid_value):
    """ Get file identifier value
    """
    file_id_prefix = 'node'
    hyphen = '-'
    max_filename_len = 6
    file_id_found = False
    fileid = None

    for key in key_value_data:
        if file_identifier and not file_id_found and file_identifier in key:
            key_value = key[1]
            file_id_found = True

    # Default
    value = str(fileid_value + 1)
    zeros_prefix_len = max_filename_len - len(value)
    zero_prefix_str = '0' * zeros_prefix_len
    # Set fileid
    fileid = file_id_prefix + hyphen + zero_prefix_str + value

    # If fileid is provided, suffixed here
    if file_id_found:
        fileid = fileid + hyphen + key_value

    log.debug("File id set to: {}".format(fileid))

    return fileid
예제 #12
0
def _certs_files_init(dest_filename):
    log.debug("In certs files init")
    # Open dest nodeid and certs csv file
    dest_csv_file = open(dest_filename, "w+")
    dest_csv_file = _write_header_to_dest_csv(dest_csv_file)
    log.debug('Node id and Cert header keys written '
              'to csv file successfully')
    return dest_csv_file
예제 #13
0
 def __init__(self, token):
     """
     Instantiate node_mfg with user token (session)
     """
     self.request_header = {
         'content-type': 'application/json',
         'Authorization': token
     }
     log.debug("Node Mfg request header: {}".format(self.request_header))
예제 #14
0
 def __init__(self, email_id):
     """
     Instantiate user with email_id.
     """
     self.__email = email_id
     self.request_header = {'content-type': 'application/json'}
     log.debug('Login setup - email: {} '
               'request_header: {}'.format(self.__email,
                                           self.request_header))
예제 #15
0
 def __init__(self):
     self.description = '\nESP Rainmaker Admin CLI'
     self.formatter_class = argparse.RawTextHelpFormatter
     self.parser = None
     self.args = None
     log.debug('Initialising argparser, default parameters set: '
               'description: {} formatter_class: {} parser: {} '
               'args: {}'.format(self.description, self.formatter_class,
                                 self.parser, self.args))
예제 #16
0
def _gen_common_files_dir(outdir):
    '''
    Generate common files dir
    '''
    # Create output directory for all common files generated
    common_outdir = os.path.join(outdir, 'common')
    if not os.path.isdir(common_outdir):
        distutils.dir_util.mkpath(common_outdir)
        log.debug("Directory created: {}".format(common_outdir))
    return common_outdir
예제 #17
0
def _init_file(common_outdir):
    log.debug("In init file")
    # Setup destination filename if not provided
    dest_filename = _set_filename(filename_prefix="node_certs",
                                  outdir=common_outdir,
                                  ext=".csv")
    if not dest_filename:
        return False
    log.debug("Dest filename set to: {}".format(dest_filename))
    return dest_filename
예제 #18
0
    def get_new_token(self, refresh_token):
        """
        Get new token for User Login

        :param refresh_token: Refresh Token of User
        :type refresh_token: str
        """
        try:
            backslash = '/'
            socket.setdefaulttimeout(10)
            log.debug("Extending user login session")

            # Set HTTP Request
            path = 'login'
            request_payload = {
                'user_name': self.__email,
                'refreshtoken': refresh_token
            }

            request_url = constants.HOST.rstrip(backslash) + backslash + path
            log.debug('Sending HTTP POST Request - request url: {} '
                      'request body: {}'.format(request_url,
                                                json.dumps(request_payload)))

            # Send HTTP POST Request
            log.debug('Sending HTTP {} request - url: {} data: {} '
                      'headers: {}'.format('post', request_url,
                                           json.dumps(request_payload),
                                           self.request_header))

            response = requests.post(url=request_url,
                                     data=json.dumps(request_payload),
                                     headers=self.request_header,
                                     verify=configmanager.CERT_FILE,
                                     timeout=(5.0, 5.0))
            response = json.loads(response.text)

            log.debug("Response received: {}".format(response))

            # Check response
            if 'accesstoken' in response and 'idtoken' in response:
                log.debug("User session extended successfully")
                return response['accesstoken'], response['idtoken']
            return False, False

        except SSLError as ssl_err:
            log.error(ssl_err)
        except NetworkError as net_err:
            log.error(net_err)
        except RequestTimeoutError as req_err:
            log.error(req_err)
        except RequestException as req_exc_err:
            log.error(req_exc_err)
        except Exception as err:
            raise Exception(err)
예제 #19
0
def _read_extra_values_file_header(filename):
    log.debug("Read extra values file header")
    extra_values_file = open(filename, 'r')
    comments_exist_in_file = False
    line = extra_values_file.readline().strip()
    # Comments are skipped
    while line.startswith('#'):
        comments_exist_in_file = True
        line = extra_values_file.readline().strip()
    log.debug("Current line: {}".format(line))
    return extra_values_file, line
예제 #20
0
def verify_fileid_count(extra_values_file, fileid, count):
    '''
    Verify count is less than or equal to
    number of values for fileid 
    '''
    log.debug("Verify fileid count")
    with open(extra_values_file, 'r') as values_file:
        rows = values_file.readlines()
    if count > (len(rows) - 1):
        return False
    return True
예제 #21
0
def _fileid_check(file_id, node_count, extra_values):
    log.debug("Fileid check")
    if file_id:
        # Verify fileid count
        ret_status = verify_fileid_count(extra_values, file_id, node_count)
        if not ret_status:
            log.error(
                "Count: {} provided is greater than the values for fileid: {} in file: {}"
                .format(node_count, file_id, extra_values))
            return False
    return True
예제 #22
0
def verify_mfg_files(outdir, config_filename, values_filename, file_id):
    '''
    Verify Mfg files format and data is valid
    '''
    common_outdir = os.path.join(outdir, 'common')
    mfg_args = Mfg_Args(config_filename, values_filename, None, None, None,
                        file_id)
    log.debug("Verifying mfg files")
    # Only verify files, csv is not generated here
    mfg_gen.generate(mfg_args)
    log.debug("Mfg files verified")
예제 #23
0
def _get_and_save_ca_cert_from_input(outdir, filepath):
    # Get CA Certificate Data from file
    ca_cert = get_ca_cert_from_file(filepath)
    if not ca_cert:
        return
    log.debug("CA Cert data recieved")
    # Save CA cert if given as input
    ret_status = save_cert(ca_cert, os.path.join(outdir, CACERT_FILENAME))
    if not ret_status:
        return
    log.debug("CA Cert saved")
    return ca_cert
예제 #24
0
def _create_date_dir(curr_outdir):
    '''
    Create date dir
    '''
    log.debug("Current outdir: {}".format(curr_outdir))
    date_dirname = datetime.datetime.now().strftime('%Y-%m-%d')
    outdir_path = os.path.join(curr_outdir, date_dirname)
    if not os.path.isdir(outdir_path):
        # Create new directory
        os.makedirs(outdir_path)
        log.debug("Directory created: {}".format(outdir_path))
    # New directory created is returned or existing one is returned
    return outdir_path
예제 #25
0
def _get_and_save_ca_key_from_input(outdir, filepath):
    # Get CA Certificate Private Key from file
    ca_private_key = get_ca_key_from_file(filepath)
    if not ca_private_key:
        return
    log.debug("CA Key data recieved")
    # Save CA key if given as input
    ret_status = save_key(ca_private_key, os.path.join(outdir,
                                                       CA_KEY_FILENAME))
    if not ret_status:
        return
    log.debug("CA Key saved")
    return ca_private_key
예제 #26
0
    def _set_default_function(self, parser, cmd=""):
        '''
        Set default function for parser

        :param parser: Parent parser to set command for
        :type parser: <Argparse parser>

        :param cmd: CLI Command
        :type cmd: str
        '''
        func = COMMANDS[cmd]["func"]
        func_name = getattr(rmaker_admin_cmd.cmds, func)
        parser.set_defaults(func=func_name)
        log.debug("Default function set: {}".format(func))
예제 #27
0
def _gen_prov_data(node_id_dir, node_id_dir_str, qrcode_outdir, random_hex_str,
                   prov_type):
    '''
    Generate Provisioning data
    QR code image and string
    '''
    log.debug("Generating QR code")
    # Set destination filename to save QR code image (png format)
    qrcode_payload_str = 'qrcode'
    # QR code image filename str is same as the current node id dirname str
    qrcode_img_str = node_id_dir_str
    # Generate payload (qr code payload) and png (qr code image)
    qrcode_payload, qrcode = generate_qrcode(random_hex_str, prov_type)
    log.debug("QR code and payload generated")
    # Save qrcode payload
    payload_file = save_to_file(qrcode_payload,
                                node_id_dir,
                                filename_prefix=qrcode_payload_str,
                                ext=".txt")
    if not payload_file:
        return
    log.debug("QR code payload saved to file")
    # Save qrcode image to file
    qrcode_img_file = save_to_file(qrcode,
                                   qrcode_outdir,
                                   filename_prefix=qrcode_img_str,
                                   ext=".png")
    if not qrcode_img_file:
        return
    log.debug("QR code image saved to file")
    return True
예제 #28
0
def _create_mfg_config_file(outdir):
    # Set csv file data
    config_csv_file = [
        'rmaker_creds,namespace,', 'node_id,data,binary',
        'mqtt_host,file,binary', 'client_cert,file,binary',
        'client_key,file,binary', 'random,file,hex2bin'
    ]

    # Check if additonal config file is given
    # in the .ini file
    ret_val = _add_extra_config_file(config_csv_file)
    # Update main config file if return is a success
    if ret_val:
        config_csv_file = ret_val

    log.debug("Final config csv file created: {}".format(config_csv_file))
    log.debug("Creating manufacturing config file")
    dest_config_filename = os.path.join(outdir, MFG_CONFIG_FILENAME)
    log.debug("Config file dest: {}".format(dest_config_filename))
    with open(dest_config_filename, 'w+') as info_file:
        for input_line in config_csv_file:
            info_file.write(input_line)
            info_file.write("\n")
    log.debug("Manufacturing config file created")
    return dest_config_filename
예제 #29
0
    def get_token_attribute(self, attribute_name, token):
        '''
        Get User token attribute

        :param attribute_name: Token Attribute Name
        :type attribute_name: str

        :param token: User Token
        :type token: str
        '''
        log.debug("Getting token attribute")
        token_payload = token.split('.')[1]
        if len(token_payload) % 4:
            token_payload += '=' * (4 - len(token_payload) % 4)
        log.debug("Token Payload: {}".format(token_payload))
        try:
            str_token_payload = base64.b64decode(token_payload).decode("utf-8")
            log.debug("Token Playload String: {}".format(str_token_payload))
            attribute_value = json.loads(str_token_payload)[attribute_name]
            log.debug("Attribute Value: {}".format(attribute_value))
            if attribute_value is None:
                log.error(InvalidConfigError())
            return attribute_value
        except Exception as err:
            raise Exception(err)
예제 #30
0
def _gen_random_info(node_id_dir):
    log.debug("Generating random info")
    # Set destination filename to save random info str (PoP)
    random_info_str = 'random'
    # Save random str (used a PoP) into a file
    random_hex_str = gen_hex_str()
    random_str_file = save_to_file(random_hex_str,
                                   node_id_dir,
                                   filename_prefix=random_info_str,
                                   ext=".txt")
    if not random_str_file:
        return False, False
    log.debug("Random info generated")
    return random_hex_str, random_str_file