# Buggy code
def update():
    """
    Update caches of the storage containers.

    Compares the md5 of the files on disk to the md5 of the blobs in the
    container, and only updates if necessary.

    Also processes deletions by walking the container caches and comparing
    with the list of blobs in the container
    """
    for container in __opts__["azurefs"]:
        path = _get_container_path(container)
        try:
            if not os.path.exists(path):
                os.makedirs(path)
            elif not os.path.isdir(path):
                shutil.rmtree(path)
                os.makedirs(path)
        except Exception as exc:
            log.exception("Error occurred creating cache directory for azurefs")
            continue
        blob_service = _get_container_service(container)
        name = container["container_name"]
        try:
            blob_list = blob_service.list_blobs(name)
        except Exception as exc:
            log.exception("Error occurred fetching blob list for azurefs")
            continue

        # Walk the cache directory searching for deletions
        blob_names = [blob.name for blob in blob_list]
        blob_set = set(blob_names)
        for root, dirs, files in os.walk(path):
            for f in files:
                fname = os.path.join(root, f)
                relpath = os.path.relpath(fname, path)
                if relpath not in blob_set:
                    salt.fileserver.wait_lock(fname + ".lk", fname)
                    try:
                        os.unlink(fname)
                    except Exception:
                        pass
            if not dirs and not files:
                shutil.rmtree(root)

        for blob in blob_list:
            fname = os.path.join(path, blob.name)
            update = False
            if os.path.exists(fname):
                # File exists, check the hashes
                source_md5 = blob.properties.content_settings.content_md5
                local_md5 = base64.b64encode(
                    salt.utils.get_hash(fname, "md5").decode("hex")
                )
                if local_md5 != source_md5:
                    update = True
            else:
                update = True

            if update:
                if not os.path.exists(os.path.dirname(fname)):
                    os.makedirs(os.path.dirname(fname))
                # Lock writes
                lk_fn = fname + ".lk"
                salt.fileserver.wait_lock(lk_fn, fname)
                with salt.utils.fopen(lk_fn, "w+") as fp_:
                    fp_.write("")

                try:
                    blob_service.get_blob_to_path(name, blob.name, fname)
                except Exception as exc:
                    log.exception("Error occurred fetching blob from azurefs")
                    continue

                # Unlock writes
                try:
                    os.unlink(lk_fn)
                except Exception:
                    pass

        # Write out file list
        container_list = path + ".list"
        lk_fn = container_list + ".lk"
        salt.fileserver.wait_lock(lk_fn, container_list)
        with salt.utils.fopen(lk_fn, "w+") as fp_:
            fp_.write("")
        with salt.utils.fopen(container_list, "w") as fp_:
            fp_.write(json.dumps(blob_names))
        try:
            os.unlink(lk_fn)
        except Exception:
            pass
        try:
            hash_cachedir = os.path.join(__opts__["cachedir"], "azurefs", "hashes")
            shutil.rmtree(hash_cachedir)
        except Exception:
            log.exception("Problem occurred trying to invalidate hash cach for azurefs")


# Traceback (OSError)
[root@ip-10-249-71-213 ~]# hubble hubble.audit
[ERROR ] Problem occurred trying to invalidate hash cach for azurefs
Traceback (most recent call last):
File "/opt/hubble/hubble-libs/hubblestack/extmods/fileserver/azurefs.py", line 268, in update
shutil.rmtree(hash_cachedir)
File "shutil.py", line 239, in rmtree
File "shutil.py", line 237, in rmtree
OSError: [Errno 2] No such file or directory: '/var/cache/hubble/azurefs/hashes'
[ERROR ] Problem occurred trying to invalidate hash cach for azurefs
Traceback (most recent call last):
File "/opt/hubble/hubble-libs/hubblestack/extmods/fileserver/azurefs.py", line 268, in update
shutil.rmtree(hash_cachedir)
File "shutil.py", line 239, in rmtree
File "shutil.py", line 237, in rmtree
OSError: [Errno 2] No such file or directory: '/var/cache/hubble/azurefs/hashes'
[ERROR ] Problem occurred trying to invalidate hash cach for azurefs
Traceback (most recent call last):
File "/opt/hubble/hubble-libs/hubblestack/extmods/fileserver/azurefs.py", line 268, in update
shutil.rmtree(hash_cachedir)
File "shutil.py", line 239, in rmtree
File "shutil.py", line 237, in rmtree
OSError: [Errno 2] No such file or directory: '/var/cache/hubble/azurefs/hashes'
[ERROR ] Problem occurred trying to invalidate hash cach for azurefs
Traceback (most recent call last):
File "/opt/hubble/hubble-libs/hubblestack/extmods/fileserver/azurefs.py", line 268, in update
shutil.rmtree(hash_cachedir)
File "shutil.py", line 239, in rmtree
File "shutil.py", line 237, in rmtree
OSError: [Errno 2] No such file or directory: '/var/cache/hubble/azurefs/hashes'
[ERROR ] Problem occurred trying to invalidate hash cach for azurefs
Traceback (most recent call last):
File "/opt/hubble/hubble-libs/hubblestack/extmods/fileserver/azurefs.py", line 268, in update
shutil.rmtree(hash_cachedir)
File "shutil.py", line 239, in rmtree
File "shutil.py", line 237, in rmtree
OSError: [Errno 2] No such file or directory: '/var/cache/hubble/azurefs/hashes'
[ERROR ] Problem occurred trying to invalidate hash cach for azurefs
Traceback (most recent call last):
File "/opt/hubble/hubble-libs/hubblestack/extmods/fileserver/azurefs.py", line 268, in update
shutil.rmtree(hash_cachedir)
File "shutil.py", line 239, in rmtree
File "shutil.py", line 237, in rmtree
OSError: [Errno 2] No such file or directory: '/var/cache/hubble/azurefs/hashes'
{'Compliance': '97%',
'Controlled': [{'CIS-1.1.8': 'AMI does not have this partition, will fix in hubble'},
{'CIS-1.1.3': 'AMI does not have this partition, will fix in hubble'},
{'CIS-1.1.5': 'AMI does not have this partition, will fix in hubble'},
{'CIS-1.1.4': 'AMI does not have this partition, will fix in hubble'},
{'CIS-1.1.9': 'AMI does not have this partition, will fix in hubble'},
{'CIS-5.2.15': 'Disabling it as per sos ticket 1307'},
{'CIS-4.2.1.4': 'Needs investigation spartans/hubble#4'},
{'CIS-4.2.2.3': 'We do not use syslog-ng in Image factory'},
{'CIS-1.1.10': 'AMI does not have this partition, will fix in hubble'},
{'CIS-2.2.1.3': 'We do not use chrony in AMI factory, we use ntpd'},
{'CIS-1.3.2': 'We use Hubble'},
{'CIS-1.1.14': 'AMI does not have this partition, will fix in hubble'},
{'CIS-4.2.2.1': 'We do not use syslog-ng in Image factory'},
{'CIS-4.2.4': 'Logged bug as sos 1441'},
{'CIS-2.2.15': 'Bug in Hubble - spartans/hubble#1'},
{'CIS-3.3.1': 'Seems bug in Hubble - spartans/hubble#5'},
{'CIS-3.3.2': 'Seems bug in Hubble - spartans/hubble#5'}],
'Failure': [{'CIS-5.2.16': 'Ensure SSH warning banner is configured'},
{'CIS-5.2.1': 'Ensure permissions on /etc/ssh/sshd_config are configured'},
{'CIS-5.2.12': 'Ensure only approved MAC algorithms are used'},
{'CIS-6.2.6': 'Ensure root PATH Integrity'}],
'Success': [{'CIS-2.2.5': 'Ensure DHCP Server is not enabled'},
{'CIS-2.3.1': 'Ensure NIS Client is not installed'},
{'CIS-2.3.2': 'Ensure rsh client is not installed'},
{'CIS-2.3.3': 'Ensure talk client is not installed'},
{'CIS-2.3.4': 'Ensure telnet client is not installed'},
{'CIS-2.3.5': 'Ensure LDAP client is not installed'},
{'CIS-2.2.3': 'Ensure Avahi Server is not enabled'},
{'CIS-2.2.4': 'Ensure CUPS is not enabled'},
{'CIS-2.1.9': 'Ensure tftp server is not enabled'},
{'CIS-2.2.2': 'Ensure X Window System is not installed'},
{'CIS-2.2.9': 'Ensure FTP Server is not enabled'},
{'CIS-1.5.4': 'Ensure prelink is disabled'},
{'CIS-2.2.6': 'Ensure LDAP server is not enabled'},
{'CIS-2.1.6': 'Ensure rsh server is not enabled'},
{'CIS-2.1.7': 'Ensure talk server is not enabled'},
{'CIS-3.6.1': 'Ensure iptables is installed'},
{'CIS-2.1.8': 'Ensure telnet server is not enabled'},
{'CIS-2.2.16': 'Ensure NIS Server is not enabled'},
{'CIS-1.3.1': 'Ensure AIDE is installed'},
{'CIS-3.4.1': 'Ensure TCP Wrappers is installed'},
{'CIS-2.1.11': 'Ensure xinetd is not enabled'},
{'CIS-5.2.2': 'Ensure SSH Protocol is set to 2'},
{'CIS-5.3.4': 'Ensure password hashing algorithm is SHA-512'},
{'CIS-5.3.3': 'Ensure password reuse is limited'},
{'CIS-5.2.7': 'Ensure SSH HostbasedAuthentication is disabled'},
{'CIS-5.3.1': 'Ensure password creation requirements are configured'},
{'CIS-5.2.5': 'Ensure SSH MaxAuthTries is set to 4 or less'},
{'CIS-5.2.9': 'Ensure SSH PermitEmptyPasswords is disabled'},
{'CIS-1.4.2': 'Ensure authentication required for single user mode'},
{'CIS-1.4.3': 'Ensure interactive boot is not enabled'},
{'CIS-1.5.1': 'Ensure core dumps are restricted'},
{'CIS-5.2.6': 'Ensure SSH IgnoreRhosts is enabled'},
{'CIS-5.3.2': 'Ensure lockout for failed password attempts is configured'},
{'CIS-5.2.14': 'Ensure SSH LoginGraceTime is set to one minute or less'},
{'CIS-6.2.3': 'Ensure no legacy "+" entries exist in /etc/shadow'},
{'CIS-6.2.2': 'Ensure no legacy "+" entries exist in /etc/passwd'},
{'CIS-5.2.10': 'Ensure SSH PermitUserEnvironment is disabled'},
{'CIS-6.2.4': 'Ensure no legacy "+" entries exist in /etc/group'},
{'CIS-5.2.13': 'Ensure SSH Idle Timeout Interval is configured'},
{'CIS-5.2.8': 'Ensure SSH root login is disabled'},
{'CIS-3.4.2': 'Ensure /etc/hosts.allow is configured'},
{'CIS-3.4.3': 'Ensure /etc/hosts.deny is configured'},
{'CIS-1.7.1.1': 'Ensure message of the day is configured properly'},
{'CIS-5.4.1.1': 'Ensure password expiration is 90 days or less'},
{'CIS-4.2.1.3': 'Ensure rsyslog default file permissions configured'},
{'CIS-5.4.1.3': 'Ensure password expiration warning days is 7 or more'},
{'CIS-5.4.1.2': 'Ensure minimum days between password changes is 7 or more'},
{'CIS-1.1.1.4': 'Ensure mounting of hfs filesystems is disabled'},
{'CIS-1.1.1.8': 'Ensure mounting of FAT filesystems is disabled'},
{'CIS-1.1.1.6': 'Ensure mounting of squashfs filesystems is disabled'},
{'CIS-1.1.1.7': 'Ensure mounting of udf filesystems is disabled'},
{'CIS-1.1.1.1': 'Ensure mounting of cramfs filesystems is disabled'},
{'CIS-1.1.1.2': 'Ensure mounting of freevxfs filesystems is disabled'},
{'CIS-1.1.1.3': 'Ensure mounting of jffs2 filesystems is disabled'},
{'CIS-3.6.2': 'Ensure default deny firewall policy'},
{'CIS-3.6.3': 'Ensure loopback traffic is configured'},
{'CIS-1.2.3': 'Ensure gpgcheck is globally activated'},
{'CIS-1.1.1.5': 'Ensure mounting of hfsplus filesystems is disabled'},
{'CIS-5.2.4': 'Ensure SSH X11 forwarding is disabled'},
{'CIS-2.2.1.2': 'Ensure ntp is configured'},
{'CIS-5.4.1.4': 'Ensure inactive password lock is 30 days or less'},
{'CIS-5.5': 'Ensure access to the su command is restricted'},
{'CIS-5.4.4': 'Ensure default user umask is 027 or more restrictive'},
{'CIS-5.2.3': 'Ensure SSH LogLevel is set to INFO'},
{'CIS-1.1.15': 'Ensure nodev option set on /dev/shm partition'},
{'CIS-1.1.17': 'Ensure noexec option set on /dev/shm partition'},
{'CIS-1.1.16': 'Ensure nosuid option set on /dev/shm partition'},
{'CIS-1.1.19': 'Disable Automounting'},
{'CIS-2.2.7': 'Ensure NFS and RPC are not enabled'},
{'CIS-4.2.1.1': 'Ensure rsyslog Service is enabled'},
{'CIS-2.2.8': 'Ensure DNS Server is not enabled'},
{'CIS-2.1.2': 'Ensure daytime services are not enabled'},
{'CIS-2.1.3': 'Ensure discard services are not enabled'},
{'CIS-5.1.1': 'Ensure cron daemon is enabled'},
{'CIS-2.1.1': 'Ensure chargen services are not enabled'},
{'CIS-2.1.10': 'Ensure rsync service is not enabled'},
{'CIS-2.1.4': 'Ensure echo services are not enabled'},
{'CIS-2.1.5': 'Ensure time services are not enabled'},
{'CIS-2.2.14': 'Ensure SNMP Server is not enabled'},
{'CIS-2.2.11': 'Ensure IMAP and POP3 server is not enabled'},
{'CIS-2.2.10': 'Ensure HTTP server is not enabled'},
{'CIS-2.2.13': 'Ensure HTTP Proxy Server is not enabled'},
{'CIS-2.2.12': 'Ensure Samba is not enabled'},
{'CIS-6.1.9': 'Ensure permissions on /etc/gshadow- are configured'},
{'CIS-6.1.8': 'Ensure permissions on /etc/group- are configured'},
{'CIS-1.4.1': 'Ensure permissions on bootloader config are configured'},
{'CIS-3.4.4': 'Ensure permissions on /etc/hosts.allow are configured'},
{'CIS-5.1.2': 'Ensure permissions on /etc/crontab are configured'},
{'CIS-3.4.5': 'Ensure permissions on /etc/hosts.deny are configured'},
{'CIS-6.1.3': 'Ensure permissions on /etc/shadow are configured'},
{'CIS-5.1.5': 'Ensure permissions on /etc/cron.weekly are configured'},
{'CIS-5.1.4': 'Ensure permissions on /etc/cron.daily are configured'},
{'CIS-5.1.7': 'Ensure permissions on /etc/cron.d are configured'},
{'CIS-5.1.6': 'Ensure permissions on /etc/cron.monthly are configured'},
{'CIS-5.1.3': 'Ensure permissions on /etc/cron.hourly are configured'},
{'CIS-1.7.1.5': 'Ensure permissions on /etc/issue are configured'},
{'CIS-6.1.6': 'Ensure permissions on /etc/passwd- are configured'},
{'CIS-6.1.7': 'Ensure permissions on /etc/shadow- are configured'},
{'CIS-6.1.4': 'Ensure permissions on /etc/group are configured'},
{'CIS-6.1.5': 'Ensure permissions on /etc/gshadow are configured'},
{'CIS-6.1.2': 'Ensure permissions on /etc/passwd are configured'},
{'CIS-5.1.8': 'Ensure at/cron is restricted to authorized users'},
{'CIS-4.2.3': 'Ensure rsyslog or syslog-ng is installed'},
{'CIS-6.2.1': 'Ensure password fields are not empty'},
{'CIS-6.2.5': 'Ensure root is the only UID 0 account'},
{'CIS-5.2.11': 'Ensure only approved ciphers are used'},
{'CIS-6.2.9': 'Ensure users own their home directories'},
{'CIS-6.2.8': "Ensure users' home directories permissions are 750 or more restrictive"},
{'CIS-1.1.18': 'Ensure sticky bit is set on all world-writable directories'},
{'CIS-5.4.2': 'Ensure system accounts are non-login'},
{'CIS-5.4.3': 'Ensure default group for the root account is GID 0'},
{'CIS-6.1.10': 'Ensure no world writable files exist'},
{'CIS-6.1.11': 'Ensure no unowned files or directories exist'},
{'CIS-6.1.12': 'Ensure no ungrouped files or directories exist'},
{'CIS-3.2.4': 'Ensure suspicious packets are logged'},
{'CIS-3.2.5': 'Ensure broadcast ICMP requests are ignored'},
{'CIS-3.2.6': 'Ensure bogus ICMP responses are ignored'},
{'CIS-3.2.7': 'Ensure Reverse Path Filtering is enabled'},
{'CIS-3.2.1': 'Ensure source routed packets are not accepted'},
{'CIS-3.2.2': 'Ensure ICMP redirects are not accepted'},
{'CIS-3.2.3': 'Ensure secure ICMP redirects are not accepted'},
{'CIS-3.1.2': 'Ensure packet redirect sending is disabled'},
{'CIS-3.1.1': 'Ensure IP forwarding is disabled'},
{'CIS-3.2.8': 'Ensure TCP SYN Cookies is enabled'},
{'CIS-1.5.3': 'Ensure address space layout randomization (ASLR) is enabled'}]}

# Fixed code
def update():
    """
    Update caches of the storage containers.

    Compares the md5 of the files on disk to the md5 of the blobs in the
    container, and only updates if necessary.

    Also processes deletions by walking the container caches and comparing
    with the list of blobs in the container
    """
    for container in __opts__["azurefs"]:
        path = _get_container_path(container)
        try:
            if not os.path.exists(path):
                os.makedirs(path)
            elif not os.path.isdir(path):
                shutil.rmtree(path)
                os.makedirs(path)
        except Exception as exc:
            log.exception("Error occurred creating cache directory for azurefs")
            continue
        blob_service = _get_container_service(container)
        name = container["container_name"]
        try:
            blob_list = blob_service.list_blobs(name)
        except Exception as exc:
            log.exception("Error occurred fetching blob list for azurefs")
            continue

        # Walk the cache directory searching for deletions
        blob_names = [blob.name for blob in blob_list]
        blob_set = set(blob_names)
        for root, dirs, files in os.walk(path):
            for f in files:
                fname = os.path.join(root, f)
                relpath = os.path.relpath(fname, path)
                if relpath not in blob_set:
                    salt.fileserver.wait_lock(fname + ".lk", fname)
                    try:
                        os.unlink(fname)
                    except Exception:
                        pass
            if not dirs and not files:
                shutil.rmtree(root)

        for blob in blob_list:
            fname = os.path.join(path, blob.name)
            update = False
            if os.path.exists(fname):
                # File exists, check the hashes
                source_md5 = blob.properties.content_settings.content_md5
                local_md5 = base64.b64encode(
                    salt.utils.get_hash(fname, "md5").decode("hex")
                )
                if local_md5 != source_md5:
                    update = True
            else:
                update = True

            if update:
                if not os.path.exists(os.path.dirname(fname)):
                    os.makedirs(os.path.dirname(fname))
                # Lock writes
                lk_fn = fname + ".lk"
                salt.fileserver.wait_lock(lk_fn, fname)
                with salt.utils.fopen(lk_fn, "w+") as fp_:
                    fp_.write("")

                try:
                    blob_service.get_blob_to_path(name, blob.name, fname)
                except Exception as exc:
                    log.exception("Error occurred fetching blob from azurefs")
                    continue

                # Unlock writes
                try:
                    os.unlink(lk_fn)
                except Exception:
                    pass

        # Write out file list
        container_list = path + ".list"
        lk_fn = container_list + ".lk"
        salt.fileserver.wait_lock(lk_fn, container_list)
        with salt.utils.fopen(lk_fn, "w+") as fp_:
            fp_.write("")
        with salt.utils.fopen(container_list, "w") as fp_:
            fp_.write(json.dumps(blob_names))
        try:
            os.unlink(lk_fn)
        except Exception:
            pass
        try:
            hash_cachedir = os.path.join(__opts__["cachedir"], "azurefs", "hashes")
            if os.path.exists(hash_cachedir):
                shutil.rmtree(hash_cachedir)
        except Exception:
            log.exception("Problem occurred trying to invalidate hash cach for azurefs")