Exemple #1
0
 def get_auto_deps(self, items):
     deps = set()
     for item in items:
         if item == self:
             continue
         if ((item.ITEM_TYPE_NAME == "file"
              and is_subdirectory(item.name, self.name))
                 or (item.ITEM_TYPE_NAME in ("file", "symlink")
                     and item.name == self.name)):
             raise BundleError(
                 _("{item1} (from bundle '{bundle1}') blocking path to "
                   "{item2} (from bundle '{bundle2}')").format(
                       item1=item.id,
                       bundle1=item.bundle.name,
                       item2=self.id,
                       bundle2=self.bundle.name,
                   ))
         if (item.ITEM_TYPE_NAME == "directory" and item.name == self.name):
             if item.attributes['purge']:
                 raise BundleError(
                     _("cannot git_deploy into purged directory {}").format(
                         item.name))
             else:
                 deps.add(item.id)
     return deps
Exemple #2
0
    def validate_attributes(cls, bundle, item_id, attributes):
        if attributes.get('delete', False):
            for attr in attributes.keys():
                if attr not in ['delete'] + list(
                        BUILTIN_ITEM_ATTRIBUTES.keys()):
                    raise BundleError(
                        _("{item} from bundle '{bundle}' cannot have other "
                          "attributes besides 'delete'").format(
                              item=item_id, bundle=bundle.name))

        if 'hash_method' in attributes and \
                attributes['hash_method'] not in HASH_METHODS:
            raise BundleError(
                _("Invalid hash method for {item} in bundle '{bundle}': '{method}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                      method=attributes['hash_method'],
                  ))

        if 'password_hash' in attributes and ('password' in attributes
                                              or 'salt' in attributes):
            raise BundleError(
                _("{item} in bundle '{bundle}': 'password_hash' "
                  "cannot be used with 'password' or 'salt'").format(
                      bundle=bundle.name, item=item_id))

        if 'salt' in attributes and 'password' not in attributes:
            raise BundleError(
                _("{}: salt given without a password").format(item_id))
Exemple #3
0
    def validate_name(cls, bundle, name):
        for char in name:
            if char not in _USERNAME_VALID_CHARACTERS:
                raise BundleError(_(
                    "Invalid character in group name '{name}': {char} (bundle '{bundle}')"
                ).format(
                    char=char,
                    bundle=bundle.name,
                    name=name,
                ))

        if name.endswith("_") or name.endswith("-"):
            raise BundleError(_(
                "Group name '{name}' must not end in dash or underscore (bundle '{bundle}')"
            ).format(
                bundle=bundle.name,
                name=name,
            ))

        if len(name) > 30:
            raise BundleError(_(
                "Group name '{name}' is longer than 30 characters (bundle '{bundle}')"
            ).format(
                bundle=bundle.name,
                name=name,
            ))
Exemple #4
0
 def validate_attributes(cls, bundle, item_id, attributes):
     if not attributes.get('delete', False):
         if attributes.get('password') is None and attributes.get(
                 'password_hash') is None:
             raise BundleError(
                 _("expected either 'password' or 'password_hash' on {item} in bundle '{bundle}'"
                   ).format(
                       bundle=bundle.name,
                       item=item_id,
                   ))
     if attributes.get('password') is not None and attributes.get(
             'password_hash') is not None:
         raise BundleError(
             _("can't define both 'password' and 'password_hash' on {item} in bundle '{bundle}'"
               ).format(
                   bundle=bundle.name,
                   item=item_id,
               ))
     if not isinstance(attributes.get('delete', True), bool):
         raise BundleError(
             _("expected boolean for 'delete' on {item} in bundle '{bundle}'"
               ).format(
                   bundle=bundle.name,
                   item=item_id,
               ))
Exemple #5
0
    def _validate_attribute_names(cls, bundle, item_id, attributes):
        if not isinstance(attributes, dict):
            raise BundleError(
                _("invalid item '{item}' in bundle '{bundle}': not a dict").
                format(
                    item=item_id,
                    bundle=bundle.name,
                ))
        invalid_attributes = set(attributes.keys()).difference(
            set(cls.ITEM_ATTRIBUTES.keys()).union(
                set(BUILTIN_ITEM_ATTRIBUTES.keys())), )
        if invalid_attributes:
            raise BundleError(
                _("invalid attribute(s) for '{item}' in bundle '{bundle}': {attrs}"
                  ).format(
                      item=item_id,
                      bundle=bundle.name,
                      attrs=", ".join(invalid_attributes),
                  ))

        invalid_attributes = set(attributes.get(
            'when_creating',
            {}).keys()).difference(set(cls.WHEN_CREATING_ATTRIBUTES.keys()))
        if invalid_attributes:
            raise BundleError(
                _("invalid when_creating attribute(s) for '{item}' in bundle '{bundle}': {attrs}"
                  ).format(
                      item=item_id,
                      bundle=bundle.name,
                      attrs=", ".join(invalid_attributes),
                  ))
Exemple #6
0
 def validate_name(cls, bundle, name):
     if normpath(name) == "/":
         raise BundleError(_("'/' cannot be a file"))
     if normpath(name) != name:
         raise BundleError(
             _("'{path}' is an invalid symlink path, should be '{normpath}' (bundle '{bundle}')"
               ).format(
                   path=name,
                   normpath=normpath(name),
                   bundle=bundle.name,
               ))
Exemple #7
0
 def get_auto_deps(self, items):
     deps = []
     for item in items:
         if item == self:
             continue
         if ((
                 item.ITEM_TYPE_NAME == "file" and
                 is_subdirectory(item.name, self.name)
             ) or (
                 item.ITEM_TYPE_NAME in ("file", "symlink") and
                 item.name == self.name
         )):
             raise BundleError(_(
                 "{item1} (from bundle '{bundle1}') blocking path to "
                 "{item2} (from bundle '{bundle2}')"
             ).format(
                 item1=item.id,
                 bundle1=item.bundle.name,
                 item2=self.id,
                 bundle2=self.bundle.name,
             ))
         elif item.ITEM_TYPE_NAME == "user" and item.name == self.attributes['owner']:
             if item.attributes['delete']:
                 raise BundleError(_(
                     "{item1} (from bundle '{bundle1}') depends on item "
                     "{item2} (from bundle '{bundle2}') which is set to be deleted"
                 ).format(
                     item1=self.id,
                     bundle1=self.bundle.name,
                     item2=item.id,
                     bundle2=item.bundle.name,
                 ))
             else:
                 deps.append(item.id)
         elif item.ITEM_TYPE_NAME == "group" and item.name == self.attributes['group']:
             if item.attributes['delete']:
                 raise BundleError(_(
                     "{item1} (from bundle '{bundle1}') depends on item "
                     "{item2} (from bundle '{bundle2}') which is set to be deleted"
                 ).format(
                     item1=self.id,
                     bundle1=self.bundle.name,
                     item2=item.id,
                     bundle2=item.bundle.name,
                 ))
             else:
                 deps.append(item.id)
         elif item.ITEM_TYPE_NAME in ("directory", "symlink"):
             if is_subdirectory(item.name, self.name):
                 deps.append(item.id)
     return deps
def validator_mode(item_id, value):
    value = str(value)
    if not value.isdigit():
        raise BundleError(
            _("mode for {item} should be written as digits, got: '{value}'"
              "").format(item=item_id, value=value))
    for digit in value:
        if int(digit) > 7 or int(digit) < 0:
            raise BundleError(
                _("invalid mode for {item}: '{value}'").format(item=item_id,
                                                               value=value))
    if not len(value) == 3 and not len(value) == 4:
        raise BundleError(
            _("mode for {item} should be three or four digits long, was: '{value}'"
              ).format(item=item_id, value=value))
Exemple #9
0
    def _write_local_file(self):
        """
        Makes the file contents available at the returned temporary path
        and performs local verification if necessary or requested.

        The calling method is responsible for cleaning up the file at
        the returned path (only if not a binary).
        """
        with tempfile() as tmp_file:
            if self.attributes['content_type'] == 'binary':
                local_path = self.template
            else:
                local_path = tmp_file
                with open(local_path, 'wb') as f:
                    f.write(self.content)

            if self.attributes['verify_with']:
                cmd = self.attributes['verify_with'].format(quote(local_path))
                io.debug("calling local verify command for {i}: {c}".format(
                    c=cmd, i=self.id))
                if call(cmd, shell=True) == 0:
                    io.debug("{i} passed local validation".format(i=self.id))
                else:
                    raise BundleError(
                        _("{i} failed local validation using: {c}").format(
                            c=cmd, i=self.id))

            yield local_path
Exemple #10
0
 def KIND(self):
     name = self.name.split("/", 2)[1]
     if name.lower() in (
             "clusterrole",
             "clusterrolebinding",
             "configmap",
             "cronjob",
             "customresourcedefinition",
             "daemonset",
             "deployment",
             "ingress",
             "namespace",
             "persistentvolumeclaim",
             "service",
             "secret",
             "statefulset",
     ):
         raise BundleError(
             _("Kind of {item_type}:{name} (bundle '{bundle}') "
               "on {node} clashes with builtin k8s_* item").format(
                   item_type=self.ITEM_TYPE_NAME,
                   name=self.name,
                   bundle=self.bundle.name,
                   node=self.bundle.node.name,
                   regex=self.NAME_REGEX,
               ))
     else:
         return name
    def validate_attributes(cls, bundle, item_id, attributes):
        if not attributes.get('sha256', None):
            raise BundleError(_(
                "at least one hash must be set on {item} in bundle '{bundle}'"
            ).format(
                bundle=bundle.name,
                item=item_id,
            ))

        if not attributes.get('url', None):
            raise BundleError(_(
                "you need to specify the url on {item} in bundle '{bundle}'"
            ).format(
                bundle=bundle.name,
                item=item_id,
            ))
Exemple #12
0
    def _manifest_dict(self):
        if self.attributes['manifest_processor'] == 'jinja2':
            content_processor = content_processor_jinja2
        elif self.attributes['manifest_processor'] == 'mako':
            content_processor = content_processor_mako
        else:
            content_processor = lambda item: item._template_content.encode(
                'utf-8')

        if self.attributes['manifest'] is not None or self.attributes[
                'manifest_file'] is None:
            user_manifest = self.attributes['manifest'] or {}
        elif (self.attributes['manifest_file'].endswith(".yaml")
              or self.attributes['manifest_file'].endswith(".yml")):
            user_manifest = yaml.load(content_processor(self),
                                      Loader=yaml.SafeLoader)
        elif self.attributes['manifest_file'].endswith(".json"):
            user_manifest = json.loads(content_processor(self))

        merged_manifest = merge_dict(
            {
                'kind': self.KIND,
                'metadata': {
                    'name': self.name.split("/")[-1],
                },
            },
            user_manifest,
        )

        if merged_manifest.get('apiVersion') is None:
            raise BundleError(
                _("{item} from bundle '{bundle}' needs an apiVersion in its manifest"
                  ).format(item=self.id, bundle=self.bundle.name))

        return merged_manifest
Exemple #13
0
 def validate_attributes(cls, bundle, item_id, attributes):
     if not isinstance(attributes.get('installed', True), bool):
         raise BundleError(
             _("expected boolean for 'installed' on {item} in bundle '{bundle}'"
               ).format(
                   bundle=bundle.name,
                   item=item_id,
               ))
Exemple #14
0
    def validate_attributes(cls, bundle, item_id, attributes):
        if item_id[len(cls.ITEM_TYPE_NAME) +
                   1:] not in ['filter', 'mangle', 'nat']:
            raise BundleError(
                _("table '{table}' is not allowed {item} in bundle '{bundle}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                      table=item_id[len(bundle.name) + 1:],
                  ))

        if not attributes.get('chains', None):
            raise BundleError(
                _("chains must be set on {item} in bundle '{bundle}'").format(
                    bundle=bundle.name,
                    item=item_id,
                ))
Exemple #15
0
 def validate_attributes(cls, bundle, item_id, attributes):
     if attributes.get('delete', False):
         for attr in attributes.keys():
             if attr not in ['delete'] + list(BUILTIN_ITEM_ATTRIBUTES.keys()):
                 raise BundleError(_(
                     "{item} from bundle '{bundle}' cannot have other "
                     "attributes besides 'delete'"
                 ).format(item=item_id, bundle=bundle.name))
Exemple #16
0
 def validate_attributes(cls, bundle, item_id, attributes):
     if attributes.get('delete', False):
         for attr in attributes.keys():
             if attr not in ['delete'] + list(BUILTIN_ITEM_ATTRIBUTES.keys()):
                 raise BundleError(_(
                     "{item} from bundle '{bundle}' cannot have other "
                     "attributes besides 'delete'"
                 ).format(item=item_id, bundle=bundle.name))
     if attributes.get('manifest') and attributes.get('manifest_file'):
         raise BundleError(_(
             "{item} from bundle '{bundle}' cannot have both 'manifest' and 'manifest_file'"
         ).format(item=item_id, bundle=bundle.name))
     if attributes.get('manifest_processor') not in (None, 'jinja2', 'mako'):
         raise BundleError(_(
             "{item} from bundle '{bundle}' has invalid manifest_processor "
             "(must be 'jinja2' or 'mako')"
         ).format(item=item_id, bundle=bundle.name))
    def validate_attributes(cls, bundle, item_id, attributes):
        if not isinstance(attributes.get('installed', True), bool):
            raise BundleError(
                _("expected boolean for 'installed' on {item} in bundle '{bundle}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                  ))

        if 'version' in attributes and attributes.get('installed',
                                                      True) is False:
            raise BundleError(
                _("cannot set version for uninstalled package on {item} in bundle '{bundle}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                  ))
Exemple #18
0
 def _validate_name(cls, bundle, name):
     if ":" in name:
         raise BundleError(
             _("invalid name for {type} in bundle '{bundle}': {name} (must not contain colon)"
               ).format(
                   bundle=bundle.name,
                   name=name,
                   type=cls.ITEM_TYPE_NAME,
               ))
 def validate_name(cls, bundle, name):
     if normpath(name) != name:
         raise BundleError(
             _("'{path}' is an invalid directory path, "
               "should be '{normpath}' (bundle '{bundle}')").format(
                   bundle=bundle.name,
                   normpath=normpath(name),
                   path=name,
               ))
 def validate_attributes(cls, bundle, item_id, attributes):
     for attribute in ('enabled', 'running'):
         if attributes.get(attribute, None) not in (True, False, None):
             raise BundleError(
                 _("expected boolean or None for '{attribute}' on {item} in bundle '{bundle}'"
                   ).format(
                       attribute=attribute,
                       bundle=bundle.name,
                       item=item_id,
                   ))
Exemple #21
0
    def validate_attributes(cls, bundle, item_id, attributes):
        if not attributes.get('delete', False):
            if attributes.get('password') is None and attributes.get(
                    'password_hash') is None:
                raise BundleError(
                    _("expected either 'password' or 'password_hash' on {item} in bundle '{bundle}'"
                      ).format(
                          bundle=bundle.name,
                          item=item_id,
                      ))
        if attributes.get('password') is not None and attributes.get(
                'password_hash') is not None:
            raise BundleError(
                _("can't define both 'password' and 'password_hash' on {item} in bundle '{bundle}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                  ))
        if not isinstance(attributes.get('delete', True), bool):
            raise BundleError(
                _("expected boolean for 'delete' on {item} in bundle '{bundle}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                  ))

        if not isinstance(attributes.get('db_priv', {}), dict):
            raise BundleError(
                _("expected dict for 'db_priv' on {item} in bundle '{bundle}'"
                  ).format(
                      bundle=bundle.name,
                      item=item_id,
                  ))

        for priv in attributes.get('privileges', []):
            if priv not in AVAILABLE_PRIVS:
                raise BundleError(
                    _("privilege {priv} is not valid on {item} in bundle '{bundle}'"
                      ).format(
                          priv=priv,
                          bundle=bundle.name,
                          item=item_id,
                      ))
Exemple #22
0
    def validate_attributes(cls, bundle, item_id, attributes):
        super(AptPkg, cls).validate_attributes(bundle, item_id, attributes)

        if not isinstance(attributes.get('when_creating', {}).get('start_service', True), bool):
            raise BundleError(_(
                "expected boolean for 'start_service' on {item} in bundle '{bundle}'"
            ).format(
                bundle=bundle.name,
                item=item_id,
            ))
Exemple #23
0
 def validate_name(cls, bundle, name):
     if not cls.NAME_REGEX_COMPILED.match(name):
         raise BundleError(
             _("name for {item_type}:{name} (bundle '{bundle}') "
               "on {node} doesn't match {regex}").format(
                   item_type=cls.ITEM_TYPE_NAME,
                   name=name,
                   bundle=bundle.name,
                   node=bundle.node.name,
                   regex=cls.NAME_REGEX,
               ))
Exemple #24
0
    def fix(self, status):
        # generate chains and rules from attributes
        chain_v4, chain_v6, rules_v4, rules_v6 = generate_rules_and_chains(self.name, self.attributes)

        # generate local tmp files
        fn_save_restore_v4 = generate_tmp_file_iptables_save_restore(IP_V4)
        fn_save_restore_v6 = generate_tmp_file_iptables_save_restore(IP_V6)
        fn_v4 = generate_tmp_file_rules(self.name, chain_v4, rules_v4)
        fn_v6 = generate_tmp_file_rules(self.name, chain_v6, rules_v6)

        # upload files to node
        self.node.upload(fn_save_restore_v4.name, '/tmp/iptables-restore-save', '700', 'root', 'root')
        self.node.upload(fn_save_restore_v6.name, '/tmp/ip6tables-restore-save', '700', 'root', 'root')

        self.node.upload(fn_v4.name, '/tmp/iptables.{}.rules'.format(self.name), '600', 'root', 'root')
        self.node.upload(fn_v6.name, '/tmp/ip6tables.{}.rules'.format(self.name), '600', 'root', 'root')

        # delete the temp files
        os.unlink(fn_v4.name)
        os.unlink(fn_v6.name)
        os.unlink(fn_save_restore_v4.name)
        os.unlink(fn_save_restore_v6.name)

        # test if rules are syntactically correct
        self.node.run(
            "/sbin/iptables-restore -t -T {table} /tmp/iptables.{table}.rules".format(table=self.name),
            log_output=True
        )
        self.node.run(
            "/sbin/ip6tables-restore -t -T {table} /tmp/ip6tables.{table}.rules".format(table=self.name),
            log_output=True
        )

        self.node.run("/tmp/iptables-restore-save -T {table} /tmp/iptables.{table}.rules".format(table=self.name))
        self.node.run("/tmp/ip6tables-restore-save -T {table} /tmp/ip6tables.{table}.rules".format(table=self.name))

        if self.attributes.get('check', True):
            # check if ssh port is open
            check_port = self.attributes.get('check_port', 22)
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = sock.connect_ex((self.node.hostname, check_port))
            if result != 0:
                raise BundleError(_(
                    "iptables broke connection to {port}. Waiting for reset (60s)."
                ).format(
                    port=check_port,
                ))

        self.node.run("touch /tmp/iptables_confirm")
        self.node.run("touch /tmp/ip6tables_confirm")

        # write actual iptables output to /etc/network
        self.node.run("iptables-save -t {table} > /etc/network/iptables.{table}.rules".format(table=self.name))
        self.node.run("ip6tables-save -t {table} > /etc/network/ip6tables.{table}.rules".format(table=self.name))
Exemple #25
0
    def validate_attributes(cls, bundle, item_id, attributes):
        if attributes.get('delete', False):
            for attr in attributes.keys():
                if attr not in ['delete'] + list(
                        BUILTIN_ITEM_ATTRIBUTES.keys()):
                    raise BundleError(
                        _("{item} from bundle '{bundle}' cannot have other "
                          "attributes besides 'delete'").format(
                              item=item_id, bundle=bundle.name))
        if 'content' in attributes and 'source' in attributes:
            raise BundleError(
                _("{item} from bundle '{bundle}' cannot have both 'content' and 'source'"
                  ).format(item=item_id, bundle=bundle.name))

        if 'content' in attributes and attributes.get(
                'content_type') == 'binary':
            raise BundleError(
                _("{item} from bundle '{bundle}' cannot have binary inline content "
                  "(use content_type 'base64' instead)").format(
                      item=item_id, bundle=bundle.name))

        if 'encoding' in attributes and attributes.get('content_type') in (
                'any',
                'base64',
                'binary',
        ):
            raise BundleError(
                _("content_type of {item} from bundle '{bundle}' cannot provide different encoding "
                  "(remove the 'encoding' attribute)").format(
                      item=item_id, bundle=bundle.name))

        if (attributes.get('content_type', None) == "any"
                and ('content' in attributes or 'encoding' in attributes
                     or 'source' in attributes)):
            raise BundleError(
                _("{item} from bundle '{bundle}' with content_type 'any' "
                  "must not define 'content', 'encoding' and/or 'source'").
                format(item=item_id, bundle=bundle.name))

        for key, value in attributes.items():
            ATTRIBUTE_VALIDATORS[key](item_id, value)
Exemple #26
0
 def _check_bundle_collisions(self, items):
     for item in items:
         if item == self:
             continue
         if item.id == self.id:
             raise BundleError(
                 _("duplicate definition of {item} in bundles '{bundle1}' and '{bundle2}'"
                   ).format(
                       item=item.id,
                       bundle1=item.bundle.name,
                       bundle2=self.bundle.name,
                   ))
Exemple #27
0
 def _check_bundle_collisions(self, items):
     for item in items:
         if item == self or (hasattr(item, 'pkg_manager') or isinstance(item, pkg.Pkg)):
             # Ignore pkg_*-Items
             continue
         if item.id == self.id:
             raise BundleError(_(
                 "duplicate definition of {item} in bundles '{bundle1}' and '{bundle2}'"
             ).format(
                 item=item.id,
                 bundle1=item.bundle.name,
                 bundle2=self.bundle.name,
             ))
Exemple #28
0
 def _validate_required_attributes(cls, bundle, item_id, attributes):
     missing = []
     for attrname in cls.REQUIRED_ATTRIBUTES:
         if attrname not in attributes:
             missing.append(attrname)
     if missing:
         raise BundleError(
             _("{item} in bundle '{bundle}' missing required attribute(s): {attrs}"
               ).format(
                   item=item_id,
                   bundle=bundle.name,
                   attrs=", ".join(missing),
               ))
Exemple #29
0
    def test(self):
        if self.attributes['source'] and not exists(self.template):
            raise BundleError(
                _("{item} from bundle '{bundle}' refers to missing "
                  "file '{path}' in its 'source' attribute").format(
                      bundle=self.bundle.name,
                      item=self.id,
                      path=self.template,
                  ))

        if not self.attributes['delete'] and not self.attributes[
                'content_type'] == 'any':
            with self._write_local_file():
                pass
Exemple #30
0
 def _check_bundle_collisions(self, items):
     super(KubernetesRawItem, self)._check_bundle_collisions(items)
     for item in items:
         if item == self or not isinstance(item, KubernetesItem):
             continue
         if item.KIND == self.KIND and item.resource_name == self.resource_name:
             raise BundleError(
                 _("duplicate definition of {item} (from bundle {bundle}) "
                   "as {item2} (from bundle {bundle2}) on {node}").format(
                       item=self.id,
                       bundle=self.bundle.name,
                       item2=item.id,
                       bundle2=item.bundle.name,
                       node=self.node.name,
                   ))