A lot of system administrators within the Department of Defense already use the Advanced Intrusion Detection Environment (AIDE). This is mainly because of a Security Technical Implementation Guide (STIG) that states that a file integrity checker must be configured to verify extended file attributes. There are a lot of features to AIDE, and the combination of using AIDE with Red Hat Ansible Automation Platform gives you the ability to automate important corrections to your system configuration.
Telling AIDE what to check
AIDE can be configured to check multiple file and folder attributes. For this article, I concentrate on the permissions (p), user (u), group (g), SELinux context (selinux) and SHA512 checksum (sha512). To create a rule that applies those attribute checks, define a name for that rule, then set it equal to each of the attributes separated by a plus sign (+). For example:
MYRULE = p+u+g+selinux+sha512
Then set different files or folders to the newly created file, separated by a dollar sign ($) and a space. For example:
/some/file/or/folder$ MYRULE
Of course, this isn’t all that's needed to create a working configuration file for AIDE, but the rest can be found in the aide.conf
man pages.
Here's an example of an aide.conf
file that locks down the attributes, as seen above, to a file named other.txt
in the /tmp
directory:
@@define DBDIR /var/lib/aide @@define LOGDIR /var/log/aide # The location of the database to be read. database=file:@@{DBDIR}/exampleaide.db.gz # The location of the database to be written. database_out=file:@@{DBDIR}/exampleaide.db.new.gz #Whether to gzip the output to database gzip_dbout=yes # Default. verbose=5 report_url=file:@@{LOGDIR}/exampleaide.log report_url=stdout MYRULE = p+u+g+selinux+sha512 /tmp/other.txt$ MYRULE
Running AIDE
Between STIG and your custom rules, aide.conf
can get unwieldy. AIDE, by default, uses the /etc/aide.conf
file for its rules. But you can pass in the --config
(-c
for short) option to specify an alternate configuration file. For instance, you could run aide --check --config=/etc/alternateAIDE.conf
to check the state of our other.txt file.
AIDE tells you when there's an error in a file:
Start timestamp: 1970-01-01 00:00:00 +0000 (AIDE 0.16) AIDE found differences between database and filesystemvi aide.conf Summary: Total number of entries: 3 Added entries: 0 Removed entries: 0 Changed entries: 1 ------------------------------------------------------------------------------ Changed entries: ------------------------------------------------------------------------------ f pug C S : /tmp//other.txt ------------------------------------------------------------------------------ Detailed information about changes: ------------------------------------------------------------------------------ File: /tmp/other.txt Perm : -rw-r--r– | ---Sr-xrwt Uid : 0 | 2 Gid : 0 | 2 SHA512 : dKZ3fe187ScU81Guyni0jGCsf | ziTsUMaYngwi6fafR5G1mCMm1 mX9/T9EZau2unU1+Nk7B5JKad | hr/Hi6LTHY8Pcd5esWdwCyu3jK YIKUi5kV5605/YhvRYDGWJGkx | eU2JAYR6qiDWpeIjsP7o7Yb3UE MHNTZp91sQ== | mnCzeUVtw== SELinux : unconfined_u:object_r:admin_ | unconfined_u:object_r:mnt_t:s0 home_t:s0 ------------------------------------------------------------------------------ The attributes of the (uncompressed) database(s): ------------------------------------------------------------------------------ /var/lib/aide/exampleaide.db.gz SHA1 : KCr1BWRHAuZRkD4TgxR9RadnBto= SHA256 : pbAUuhUnpyqfHt/OVAytX37hco1QuBC1 keg107hsWEk= SHA512 : ur3bt+wGZAizlbtIdINVNmdYN4U/EzZq 50Ryzj8kUutkCVIBEPoQ3apOCBOYMY2p eGfeqK3QtmdjFHsy1cUKuw== End timestamp: 1970-01-01 00:00:00 +0000 (run time: 0m 0s)
Understanding the AIDE output
A summary of incorrect attributes to the file is in the Changed entries
section:
f pug C S : /tmp/other.txt
f
: a filepug
: permissions, user, and group are incorrectC
: checksum mismatchS
: SELinux context is incorrect
If one of the attributes is correct, a dot (.
) is displayed instead of the character.
The Detailed information about changes
section provides a full explanation of differences in the file.
AIDE maintains a database, specified in aide.conf
, so that it knows what the attributes are supposed to be. In my example, you can look at the contents of the database with the zcat
command.
@@begin_db # This file was generated by Aide, version 0.16 # Time of generation was 2023-06-29 00:27:36 @@db_spec name name attr perm inode uid gid sha512 selinux /tmp/other.txt 0 6442450973 100644 138 0 0 2a0d941f74139a069df6e1df2533159b46875e1eb4cc815f600ea22e1526552556e03adb4b3ae668398f1b5fb60471ebd1c80c6686fa3507e5561adcfcb87==
All the information that the aide.conf
could want is stored within the database file.
Making use of the AIDE output and database
Now you've gotten the output of running the aide
command and viewed the contents of the database that AIDE utilizes. So what can you do with this information? You can fix these files, when AIDE shows them as being incorrect, and you can do all of this with Ansible. All you have to do is write a playbook to run your aide
command, interpret the errors, get the corrections from the AIDE database file, and then apply these fixes to the files. All of this is IF the checksums aren’t different. If the checksum ends up being different than expected, well then you have to replace the file with the correct one. But Ansible can handle replacing files with ease.
First step is to check for errors. You must use the cmd module to run the aide
command and collect the output as seen here:
- name: Check aide for Errors ansible.builtin.shell: cmd: "/usr/sbin/aide -V5 -C -c {{ aideconf }} | egrep '^d|^f'" register: values when: true failed_when: values.rc > 1
Now that you can detect errors, you need to get the proper attributes prior to fixing the attributes to what they are. Once again, you have to defer to the cmd module to run the zcat
command to view the contents of the database file.
- name: Get UID Index ansible.builtin.shell: cmd: AIDEDB=$(/bin/zcat {{ aidedb }} | grep @@db_spec); echo ${AIDEDB[@]/uid//} | cut -d/ -f1 | wc -w register: uidpos when: true - name: Set UID ansible.builtin.shell: cmd: /usr/bin/id -n -u $(/bin/zcat {{ aidedb }} | grep "{{ afile }} " | cut -d' ' -f"{{ uidpos.stdout }}") register: auid when: true
Because the database stores all possible attributes that AIDE can handle, you must set the index for the position that the attribute is in, then get that value from the database. In the above example, you can see how to do this for the UID. This must be done for each of the attributes that are checked.
Once the correct attribute is found, you can ensure that the file gets that correct attribute. First, ensure that the file needs to be fixed:
- name: Fix the File(s) ansible.builtin.include_tasks: file: fix.yml vars: afile: "{{ item.split(':')[1].split(' ')[1] }}" loop: "{{ values.stdout_lines }}" when: (item is defined) and (not "C" in item.split(':')[0]) and (item.split()[0] == 'f') and ('p' or 'u' or 'g' or 'S' in item.split(':')[0])
Then make this change:
- name: Fix {{ afile }} ansible.builtin.file: path: "{{ afile }}" owner: "{{ auid.stdout }}"
When the checksum is different
Earlier, I said you could fix the file as long as the checksum is the same. But what do you do when the checksum has changed? In this situation, you replace the incorrect file with the proper one. This can be done with the Ansible modules copy or template. You can still use all the other attributes that were pulled from the database with the module. But the whole file needs to be replaced if the checksum differs.
Automate using Red Hat Ansible Automation Platform
Now that you have some working Ansible playbooks established, it would be best to utilize Ansible Automation Platform to execute them. The platform also enables you to use the REST (REpresentational State Transfer) API. But before you can do this, you must make a few changes to how the playbook operates.
First, ensure that there are credentials that the playbook can use to access the host system. This allows the playbook to run unassisted, meaning the REST API kicks it off and no other interactions are needed. Next, require the variables Prompt at launch
. Here is where you need to allow changes to the inventory because you don’t want to run this playbook against all systems just because one system is out of configuration.
Once this is done, you can craft your REST API call to Ansible Automation Platform:
$ curl -k -X POST -u USERNAME:PASSWORD \ https://{ AAP }/api/v2/job_templates/{ Template Number }/launch/ \ -H "Content-Type: application/json" \ -d '{"extra_vars": "{host: '$(hostname)'}"}'
This command sends a POST to the platform website to execute the REST API you want to call. To execute a playbook, curl
must be able to log in to Ansible Automation Platform. This is where the -u USERNAME:PASSWORD
comes into play. For this to work, you must set up a user account within the platform that only has access to execute this one playbook.
Also, you can obfuscate the password to comply compliant to the STIG against displaying clear text passwords. First, create a password hash:
$ echo mypassword | base64 > /root/passFile.txt
Decode that password in your curl command with $(cat /root/passFile.txt | base64 --decode)
in place of PASSWORD
.
The Template Number is a number assigned to the job template based on when it was put into the Ansible platform. To get this number, go to Red Hat Ansible Automation Platform > Templates, then click on the job template name. Afterwards, the Job Template ID appears within the URL of your site. For example, if a Job Template is 9, then your URL might be https://myaap/#/templates/job_template/9/details
.
The Content-Type
section is where you tell the API, through your POST action, that you have more applicable content to add to the call. Specify that you are inserting the arguments as JSON, and then input your code. In this example, you're saying that the variable you want to reassign is called host
and that you want to reassign it to $(hostname)
. The $(hostname)
parameter tells the system to run the hostname
command. If this isn’t the same as what you have in your Ansible Automation Platform inventory, then you must make them match. For example, if you have the condensed hostname in Ansible Automation Platform, but on the host you have the FQDN, then you would pass in something like $(hostname | cut -d\. -f1)
.
Now that you have the REST API command, you can run this on the system to start your playbook automatically. Better yet, you can insert this command as a cron job to automatically return your system to the desired configuration.
AIDE and Ansible Automation Platform
AIDE is a useful and flexible tool that helps you stay compliant with STIG requirements. Combined with Red Hat Ansible Automation Platform, the most important configuration for your systems is automatic.
저자 소개
Jonathon is a Senior Solution Architect working with Department of Defense. He started with Red Hat in 2022, but has spent 15+ years within the DoD. He has spent the bulk of his career concentrating on automation. The past few years has been spent working on CI/CD Pipelines and utilizing new technologies.
채널별 검색
오토메이션
기술, 팀, 인프라를 위한 IT 자동화 최신 동향
인공지능
고객이 어디서나 AI 워크로드를 실행할 수 있도록 지원하는 플랫폼 업데이트
오픈 하이브리드 클라우드
하이브리드 클라우드로 더욱 유연한 미래를 구축하는 방법을 알아보세요
보안
환경과 기술 전반에 걸쳐 리스크를 감소하는 방법에 대한 최신 정보
엣지 컴퓨팅
엣지에서의 운영을 단순화하는 플랫폼 업데이트
인프라
세계적으로 인정받은 기업용 Linux 플랫폼에 대한 최신 정보
애플리케이션
복잡한 애플리케이션에 대한 솔루션 더 보기
오리지널 쇼
엔터프라이즈 기술 분야의 제작자와 리더가 전하는 흥미로운 스토리
제품
- Red Hat Enterprise Linux
- Red Hat OpenShift Enterprise
- Red Hat Ansible Automation Platform
- 클라우드 서비스
- 모든 제품 보기
툴
체험, 구매 & 영업
커뮤니케이션
Red Hat 소개
Red Hat은 Linux, 클라우드, 컨테이너, 쿠버네티스 등을 포함한 글로벌 엔터프라이즈 오픈소스 솔루션 공급업체입니다. Red Hat은 코어 데이터센터에서 네트워크 엣지에 이르기까지 다양한 플랫폼과 환경에서 기업의 업무 편의성을 높여 주는 강화된 기능의 솔루션을 제공합니다.