Пример #1
0
    def __init__(self, fabric_config_dict):
        if fabric_config_dict.has_key("fabric"):
            for key in self.required_keys:
                if not fabric_config_dict['fabric'].has_key(key):
                    util.log_error_and_exit(
                        "Fabric configuration file is missing " + key)
            try:
                self.edge_facing_capacity = int(
                    fabric_config_dict["fabric"]["edge_facing_capacity"])
            except ValueError:
                util.log_error_and_exit(
                    "Invalid value found for total edge facing capacity in provided fabric configuration"
                )

            for rack in fabric_config_dict['fabric']['racks']:
                rack['rack_id'] = self.rack_id
                self.total_racks += rack['rack_count']
                self.racks.append(Rack(rack))
                self.rack_facing_capacity += self.racks[
                    self.
                    rack_id].total_required_fabric_network_capacity * self.racks[
                        self.rack_id].rack_count
                self.rack_id += 1
        self.network_addressing = Network_addressing(
            fabric_config_dict['fabric']['addressing'])
        print "Total rack facing capacity required: " + str(
            self.rack_facing_capacity)
        print "Total edge facing capacity required: " + str(
            self.edge_facing_capacity)
Пример #2
0
 def __init__(self, sku_dict):
    ports = None 
    for key in self.required_keys:
       if not sku_dict.has_key(key):
          util.log_error_and_exit("SKU data is missing "+key+" for SKU: "+str(sku['sku'])) 
    for key, value in sku_dict.items():
       setattr(self, key, value)
    self.ports = Ports(self.network_interfaces)
Пример #3
0
def get_config(aws_creds_path):
    config = configparser.RawConfigParser()
    try:
        config.read(aws_creds_path)
    except configparser.ParsingError:
        e = sys.exc_info()[1]
        log_error_and_exit(
            logger, "There was a problem reading or parsing "
            "your credentials file: %s" % (e.args[0], ))
    return config
Пример #4
0
 def __init__(self, ports_list):
    self.ports_list = []
    self.count = 0
    for port in ports_list:
       for key in self.required_sku_keys:
          if not port.has_key(key):
             util.log_error_and_exit("Platform SKU network interfaces definition is missing key "+key)
    for port in ports_list:
       port['in_use'] = False
       self.ports_list.append(port)
       self.count += 1
Пример #5
0
    def generate_tor_links(self, tor, rack):
        tor_links = []
        required_ports = rack.host_ports.count
        rport_list = rack.host_ports.ports_list
        for rport in rport_list:
            for sport in tor.sku.ports.ports_list:
                if sport['in_use'] is False and util.is_form_factor_compatible(
                        sport['form_factor'], rport['form_factor']):
                    if util.is_intersect(rport['speeds'], sport['speeds']):
                        speed = rport['speeds'][0]
                        sport['in_use'] = True
                        tor_links.append(
                            Link(tor.name, sport['name'], sport['form_factor'],
                                 speed))
                        tor_links[len(tor_links) - 1].set_remote_vars(
                            "host", "host_port", sport['form_factor'], speed)
                        required_ports -= 1
                        break

        required_ports = rack.fabric_ports.count
        rport_list = rack.fabric_ports.ports_list
        for rport in rport_list:
            for sport in tor.sku.ports.ports_list:
                if sport['in_use'] is False and util.is_form_factor_compatible(
                        sport['form_factor'], rport['form_factor']):
                    if util.is_intersect(rport['speeds'], sport['speeds']):
                        speed = rport['speeds'][0]
                        sport['in_use'] = True
                        tor_links.append(
                            Link(tor.name, sport['name'], sport['form_factor'],
                                 speed))
                        tor_links[len(tor_links) - 1].set_remote_vars(
                            "next_stage", "next_stage", sport['form_factor'],
                            speed)
                        required_ports -= 1
                        break

        ###Reset in_use flag
        for sport in tor.sku.ports.ports_list:
            sport['in_use'] = False
        if required_ports > 0:
            util.log_error_and_exit(
                "generate_tor_links() failed to generate links for TOR " +
                tor_name)
        else:
            return tor_links
Пример #6
0
def initial_setup(logger, config, config_path):
    console_input = prompter()

    profile_name = console_input('Profile name to [%s]: ' % ("default"))
    if profile_name is None or profile_name == "":
        profile_name = "default"

    profile_name = "{}-long-term".format(profile_name)
    aws_access_key_id = getpass.getpass('aws_access_key_id: ')
    if aws_access_key_id is None or aws_access_key_id == "":
        log_error_and_exit(logger, "You must supply aws_access_key_id")
    aws_secret_access_key = getpass.getpass('aws_secret_access_key: ')
    if aws_secret_access_key is None or aws_secret_access_key == "":
        log_error_and_exit(logger, "You must supply aws_secret_access_key")

    config.add_section(profile_name)
    config.set(profile_name, 'aws_access_key_id', aws_access_key_id)
    config.set(profile_name, 'aws_secret_access_key', aws_secret_access_key)
    with open(config_path, 'w') as configfile:
        config.write(configfile)
Пример #7
0
 def __init__(self, ports_list):
     self.ports_list = []
     self.count = 0
     for port in ports_list:
         for key in self.required_rack_keys:
             if not port.has_key(key):
                 util.log_error_and_exit(
                     "Rack SKU host_network_interfaces definition is missing key "
                     + key)
     for port in ports_list:
         for count in range(0, int(port['count'])):
             port_definition = {
                 'name': self.count,
                 'form_factor': port['form_factor'],
                 'speeds': [port['speed']],
                 'breakouts': [],
                 'port_group': self.count,
                 'in_use': False
             }
             self.ports_list.append(port_definition)
             self.count += 1
Пример #8
0
   def __init__(self, network_interfaces_list, rack_name):
      for key in self.supported_form_factors:
         self.host_interfaces_total[key] = 0

      for nic in network_interfaces_list:
         for key in self.required_keys:
            if not nic.has_key(key):
               util.log_error_and_exit("Missing key of "+str(key)+" from configuration for rack "+str(rack_name))
         if nic['speed'] not in self.supported_speeds:
            util.log_error_and_exit("Network interface speed of "+str(nic['speed'])+" is not supported")
         if nic['form_factor'] not in self.supported_form_factors:
            util.log_error_and_exit("Network interface form_factor of "+str(nic['optic'])+" is not supported")
         self.host_interfaces_total[nic['form_factor']] += 1 * nic['count']
Пример #9
0
    def __init__(self, rack_dict):
        for attribute in self.required_attributes:
            if not rack_dict.has_key(attribute):
                util.log_error_and_exit(
                    attribute +
                    " is a mandatory variable and is missing from the provided configuration file"
                )
        for key, value in rack_dict.items():
            setattr(self, key, value)

        try:
            self.rack_count = int(rack_dict["rack_count"])
        except ValueError:
            util.log_error_and_exit(
                "Invalid value found for rack count for rack " +
                str(self.name) + " in provided fabric configuration")

        for nic in self.host_network_interfaces:
            ###Sum the total required host network capacity in the rack
            self.total_required_host_network_capacity += nic['speed'] * nic[
                'count']
            ###Determine the fastest host facing interface speed in the rack
            if nic['speed'] > self.largest_potential_flow_size:
                self.largest_potential_flow_size = nic['speed']

        self.total_required_fabric_network_capacity = math.ceil(
            util.calculate_sub_ratio(self.subscription_ratio_to_fabric) *
            self.total_required_host_network_capacity)
        if (self.total_required_fabric_network_capacity < 0):
            util.log_error_and_exit("Oversubscription ratio for rack " +
                                    str(self.name) + " of " +
                                    str(self.subscription_ratio_to_fabric) +
                                    " is invalid")
        self.host_ports = Host_ports(self.host_network_interfaces)
        self.fabric_ports = Fabric_ports(
            self.total_required_fabric_network_capacity,
            self.largest_potential_flow_size)
Пример #10
0
 def __init__(self, platform_data_dict):
     if not platform_data_dict.has_key('platforms'):
         util.log_error_and_exit(
             "Platform data is missing high level 'platform' key")
     for sku in platform_data_dict['platforms']:
         self.sku_list.append(Sku(sku))
Пример #11
0
   def __init__(self, addressing_config_dict):
      for key in self.required_keys:
         if not addressing_config_dict.has_key(key):
            util.log_error_and_exit("Addressing configuration is missing "+key)
     
      ###Populate lists of available subnets and addresses
      ###FIXME: Add IPv6 support
      self.network_point_to_point_network = ipaddress.IPv4Network(unicode(addressing_config_dict['network_point_to_points']['range']),strict=True)
      self.network_point_to_point_subnets = list(self.network_point_to_point_network.subnets(new_prefix=31))
      if addressing_config_dict['network_point_to_points'].has_key('exclude'):
         for addr in addressing_config_dict['network_point_to_points']['exclude']: 
            if not util.is_ip_address(addr):
               if not util.is_ip_network(addr):
                  util.log_error_and_exit("Excluded address "+addr+" is not a valid IP address or network")
            self.network_point_to_point_exclude.append(ipaddress.IPv4Network(unicode(addr)))
      
         ###Remove any subnets that contain excluded addresses
         ###FIXME: I'm lazy and not doing LPM
         for addr in self.network_point_to_point_exclude:
            for subnet in self.network_point_to_point_subnets:
               if subnet.overlaps(addr):
                  print "Excluding subnet: "+str(subnet)
                  self.network_point_to_point_subnets.remove(subnet)

      ###Populate lists of available subnets and addresses
      ###FIXME: Add IPv6 support
      self.loopbacks_network = ipaddress.IPv4Network(unicode(addressing_config_dict['loopbacks']['range']),strict=True)
      self.loopbacks_subnets = list(self.loopbacks_network.subnets(new_prefix=32))
      if addressing_config_dict['loopbacks'].has_key('exclude'):
         for addr in addressing_config_dict['loopbacks']['exclude']:
            if not util.is_ip_address(addr):
               if not util.is_ip_network(addr):
                  util.log_error_and_exit("Excluded address "+addr+" is not a valid IP address or network")
            self.loopbacks_exclude.append(ipaddress.IPv4Network(unicode(addr)))

         ###Remove any subnets that contain excluded addresses
         ###FIXME: I'm lazy and not doing LPM
         for addr in self.loopbacks_exclude:
            for subnet in self.loopbacks_subnets:
               if subnet.overlaps(addr):
                  print "Excluding subnet: "+str(subnet)
                  self.loopbacks_subnets.remove(subnet)

      ###Populate lists of available subnets and addresses
      ###FIXME: Add IPv6 support
      self.management_network_network = ipaddress.IPv4Network(unicode(addressing_config_dict['management_network']['range']),strict=True)
      self.management_network_subnets = list(self.management_network_network.subnets(new_prefix=32))
      if addressing_config_dict['management_network'].has_key('exclude'):
         for addr in addressing_config_dict['management_network']['exclude']:
            if not util.is_ip_address(addr):
               if not util.is_ip_network(addr):
                  util.log_error_and_exit("Excluded address "+addr+" is not a valid IP address or network")
            self.management_network_exclude.append(ipaddress.IPv4Network(unicode(addr)))

         ###Remove any subnets that contain excluded addresses
         ###FIXME: I'm lazy and not doing LPM
         for addr in self.management_network_exclude:
            for subnet in self.management_network_subnets:
               if subnet.overlaps(addr):
                  print "Excluding subnet: "+str(subnet)
                  self.management_network_subnets.remove(subnet)
Пример #12
0
def get_credentials(short_term_name, lt_key_id, lt_access_key, args, config):
    console_input = prompter()
    mfa_token = console_input('Enter AWS MFA code for device [%s] '
                              '(renewing for %s seconds):' %
                              (args.device, args.duration))

    client = boto3.client('sts',
                          aws_access_key_id=lt_key_id,
                          aws_secret_access_key=lt_access_key)

    if args.assume_role:

        logger.info("Assuming Role - Profile: %s, Role: %s, Duration: %s",
                    short_term_name, args.assume_role, args.duration)
        if args.role_session_name is None:
            log_error_and_exit(
                logger, "You must specify a role session name "
                "via --role-session-name")

        try:
            response = client.assume_role(
                RoleArn=args.assume_role,
                RoleSessionName=args.role_session_name,
                DurationSeconds=args.duration,
                SerialNumber=args.device,
                TokenCode=mfa_token)
        except ClientError as e:
            log_error_and_exit(
                logger, "An error occured while calling "
                "assume role: {}".format(e))
        except ParamValidationError:
            log_error_and_exit(logger, "Token must be six digits")

        config.set(
            short_term_name,
            'assumed_role',
            'True',
        )
        config.set(
            short_term_name,
            'assumed_role_arn',
            args.assume_role,
        )
    else:
        logger.info("Fetching Credentials - Profile: %s, Duration: %s",
                    short_term_name, args.duration)
        try:
            response = client.get_session_token(DurationSeconds=args.duration,
                                                SerialNumber=args.device,
                                                TokenCode=mfa_token)
        except ClientError as e:
            log_error_and_exit(
                logger,
                "An error occured while calling assume role: {}".format(e))
        except ParamValidationError:
            log_error_and_exit(logger, "Token must be six digits")

        config.set(
            short_term_name,
            'assumed_role',
            'False',
        )
        config.remove_option(short_term_name, 'assumed_role_arn')

    # aws_session_token and aws_security_token are both added
    # to support boto and boto3
    options = [
        ('aws_access_key_id', 'AccessKeyId'),
        ('aws_secret_access_key', 'SecretAccessKey'),
        ('aws_session_token', 'SessionToken'),
        ('aws_security_token', 'SessionToken'),
    ]

    for option, value in options:
        config.set(short_term_name, option, response['Credentials'][value])
    # Save expiration individiually, so it can be manipulated
    config.set(
        short_term_name, 'expiration',
        response['Credentials']['Expiration'].strftime('%Y-%m-%d %H:%M:%S'))
    with open(AWS_CREDS_PATH, 'w') as configfile:
        config.write(configfile)
    logger.info("Success! Your credentials will expire in %s seconds at: %s" %
                (args.duration, response['Credentials']['Expiration']))
    sys.exit(0)
Пример #13
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--device',
                        required=False,
                        metavar='arn:aws:iam::123456788990:mfa/dudeman',
                        help="The MFA Device ARN. This value can also be "
                        "provided via the environment variable 'MFA_DEVICE' or"
                        " the ~/.aws/credentials variable 'aws_mfa_device'.")
    parser.add_argument('--duration',
                        type=int,
                        help="The duration, in seconds, that the temporary "
                        "credentials should remain valid. Minimum value: "
                        "900 (15 minutes). Maximum: 129600 (36 hours). "
                        "Defaults to 43200 (12 hours), or 3600 (one "
                        "hour) when using '--assume-role'. This value "
                        "can also be provided via the environment "
                        "variable 'MFA_STS_DURATION'. ")
    parser.add_argument('--profile',
                        help="If using profiles, specify the name here. The "
                        "default profile name is 'default'. The value can "
                        "also be provided via the environment variable "
                        "'AWS_PROFILE'.",
                        required=False)
    parser.add_argument('--long-term-suffix',
                        '--long-suffix',
                        help="The suffix appended to the profile name to"
                        "identify the long term credential section",
                        required=False)
    parser.add_argument('--short-term-suffix',
                        '--short-suffix',
                        help="The suffix appended to the profile name to"
                        "identify the short term credential section",
                        required=False)
    parser.add_argument('--assume-role',
                        '--assume',
                        metavar='arn:aws:iam::123456788990:role/RoleName',
                        help="The ARN of the AWS IAM Role you would like to "
                        "assume, if specified. This value can also be provided"
                        " via the environment variable 'MFA_ASSUME_ROLE'",
                        required=False)
    parser.add_argument('--role-session-name',
                        help="Friendly session name required when using "
                        "--assume-role",
                        default=getpass.getuser(),
                        required=False)
    parser.add_argument('--force',
                        help="Refresh credentials even if currently valid.",
                        action="store_true",
                        required=False)
    parser.add_argument(
        '--log-level',
        help="Set log level",
        choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'],
        required=False,
        default='DEBUG')
    parser.add_argument('--setup',
                        help="Setup a new log term credentials section",
                        action="store_true",
                        required=False)
    args = parser.parse_args()

    level = getattr(logging, args.log_level)
    setup_logger(level)

    if not os.path.isfile(AWS_CREDS_PATH):
        console_input = prompter()
        create = console_input("Could not locate credentials file at {}, "
                               "would you like to create one? "
                               "[y/n]".format(AWS_CREDS_PATH))
        if create.lower() == "y":
            with open(AWS_CREDS_PATH, 'a'):
                pass
        else:
            log_error_and_exit(
                logger, 'Could not locate credentials file at '
                '%s' % (AWS_CREDS_PATH, ))

    config = get_config(AWS_CREDS_PATH)

    if args.setup:
        initial_setup(logger, config, AWS_CREDS_PATH)
        return

    validate(args, config)
Пример #14
0
def validate(args, config):
    if not args.profile:
        if os.environ.get('AWS_PROFILE'):
            args.profile = os.environ.get('AWS_PROFILE')
        else:
            args.profile = 'default'

    if not args.long_term_suffix:
        long_term_name = '%s-long-term' % (args.profile, )
    elif args.long_term_suffix.lower() == 'none':
        long_term_name = args.profile
    else:
        long_term_name = '%s-%s' % (args.profile, args.long_term_suffix)

    if not args.short_term_suffix or args.short_term_suffix.lower() == 'none':
        short_term_name = args.profile
    else:
        short_term_name = '%s-%s' % (args.profile, args.short_term_suffix)

    if long_term_name == short_term_name:
        log_error_and_exit(
            logger, "The value for '--long-term-suffix' cannot "
            "be equal to the value for '--short-term-suffix'")

    if args.assume_role:
        role_msg = "with assumed role: %s" % (args.assume_role, )
    elif config.has_option(args.profile, 'assumed_role_arn'):
        role_msg = "with assumed role: %s" % (config.get(
            args.profile, 'assumed_role_arn'))
    else:
        role_msg = ""
    logger.info('Validating credentials for profile: %s %s' %
                (short_term_name, role_msg))
    reup_message = "Obtaining credentials for a new role or profile."

    try:
        key_id = config.get(long_term_name, 'aws_access_key_id')
        access_key = config.get(long_term_name, 'aws_secret_access_key')
    except NoSectionError:
        log_error_and_exit(
            logger, "Long term credentials session '[%s]' is missing. "
            "You must add this section to your credentials file "
            "along with your long term 'aws_access_key_id' and "
            "'aws_secret_access_key'" % (long_term_name, ))
    except NoOptionError as e:
        log_error_and_exit(logger, e)

    # get device from param, env var or config
    if not args.device:
        if os.environ.get('MFA_DEVICE'):
            args.device = os.environ.get('MFA_DEVICE')
        elif config.has_option(long_term_name, 'aws_mfa_device'):
            args.device = config.get(long_term_name, 'aws_mfa_device')
        else:
            log_error_and_exit(
                logger, 'You must provide --device or MFA_DEVICE or set '
                '"aws_mfa_device" in ".aws/credentials"')

    # get assume_role from param or env var
    if not args.assume_role:
        if os.environ.get('MFA_ASSUME_ROLE'):
            args.assume_role = os.environ.get('MFA_ASSUME_ROLE')
        elif config.has_option(long_term_name, 'assume_role'):
            args.assume_role = config.get(long_term_name, 'assume_role')

    # get duration from param, env var or set default
    if not args.duration:
        if os.environ.get('MFA_STS_DURATION'):
            args.duration = int(os.environ.get('MFA_STS_DURATION'))
        else:
            args.duration = 3600 if args.assume_role else 43200

    # If this is False, only refresh credentials if expired. Otherwise
    # always refresh.
    force_refresh = False

    # Validate presence of short-term section
    if not config.has_section(short_term_name):
        logger.info("Short term credentials section %s is missing, "
                    "obtaining new credentials." % (short_term_name, ))
        if short_term_name == 'default':
            try:
                config.add_section(short_term_name)
            # a hack for creating a section named "default"
            except ValueError:
                configparser.DEFAULTSECT = short_term_name
                config.set(short_term_name, 'CREATE', 'TEST')
                config.remove_option(short_term_name, 'CREATE')
        else:
            config.add_section(short_term_name)
        force_refresh = True
    # Validate option integrity of short-term section
    else:
        required_options = [
            'assumed_role', 'aws_access_key_id', 'aws_secret_access_key',
            'aws_session_token', 'aws_security_token', 'expiration'
        ]
        try:
            short_term = {}
            for option in required_options:
                short_term[option] = config.get(short_term_name, option)
        except NoOptionError:
            logger.warn("Your existing credentials are missing or invalid, "
                        "obtaining new credentials.")
            force_refresh = True

        try:
            current_role = config.get(short_term_name, 'assumed_role_arn')
        except NoOptionError:
            current_role = None

        if args.force:
            logger.info("Forcing refresh of credentials.")
            force_refresh = True
        # There are not credentials for an assumed role,
        # but the user is trying to assume one
        elif current_role is None and args.assume_role:
            logger.info(reup_message)
            force_refresh = True
        # There are current credentials for a role and
        # the role arn being provided is the same.
        elif (current_role is not None and args.assume_role
              and current_role == args.assume_role):
            pass
        # There are credentials for a current role and the role
        # that is attempting to be assumed is different
        elif (current_role is not None and args.assume_role
              and current_role != args.assume_role):
            logger.info(reup_message)
            force_refresh = True
        # There are credentials for a current role and no role arn is
        # being supplied
        elif current_role is not None and args.assume_role is None:
            logger.info(reup_message)
            force_refresh = True

    should_refresh = True

    # Unless we're forcing a refresh, check expiration.
    if not force_refresh:
        exp = datetime.datetime.strptime(
            config.get(short_term_name, 'expiration'), '%Y-%m-%d %H:%M:%S')
        diff = exp - datetime.datetime.utcnow()
        if diff.total_seconds() <= 0:
            logger.info("Your credentials have expired, renewing.")
        else:
            should_refresh = False
            logger.info("Your credentials are still valid for %s seconds"
                        " they will expire at %s" %
                        (diff.total_seconds(), exp))

    if should_refresh:
        get_credentials(short_term_name, key_id, access_key, args, config)