Merge pull request #35 from LCTT/master

更新
This commit is contained in:
zEpoch 2021-07-14 23:25:33 +08:00 committed by GitHub
commit 5302475302
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 587 additions and 225 deletions

View File

@ -3,31 +3,30 @@
[#]: author: (Gaurav Kamathe https://opensource.com/users/gkamathe)
[#]: collector: (lujun9972)
[#]: translator: (YungeG)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-13578-1.html)
像查询数据库一样查询你的 Linux 操作系统
像查询数据库一样查询你的 Linux 操作系统信息
======
使用数据库查询操作轻松获取系统信息。
![Magnifying glass on code][1]
> 使用数据库查询操作轻松获取系统信息。
![](https://img.linux.net.cn/data/attachment/album/202107/14/095820zywm2m2tzz5otfh5.jpg)
Linux 提供了很多帮助用户收集主机操作系统信息的命令:列出文件或者目录的属性信息;查询安装的软件包、正在执行的命令、开机时启动的服务;或者了解系统的硬件。
每个命令使用自己的输出格式列出系统的信息。你需要使用 `grep`、`sed`、`awk` 这样的工具过滤命令输出的结果,以便找到特定的信息。此外,很多这样的信息会频繁变动,导致系统状态的改变。
将所有的信息格式化为一个数据库的 SQL 查询的输出进行查看将会十分有益 。想象一下,你能够像查询具有类似名称的 SQL 数据库表一样查询 `ps``rpm` 命令的输出。
将所有的信息格式化为一个数据库的 SQL 查询的输出进行查看将会十分有益。想象一下,你能够像查询具有类似名称的 SQL 数据库表一样查询 `ps``rpm` 命令的输出。
幸运的是,有一个工具刚好实现了这个功能,而且功能更多:[Osquery][2] 是一个 [开源的][3] “SQL powered operating system instrumentation, monitoring, and analytics framework”。
幸运的是,有一个工具刚好实现了这个功能,而且功能更多:[Osquery][2] 是一个 [开源的][3] “由 SQL 驱动的操作系统仪表、监控和分析框架”。
许多处理安全、DevOps、合规性的应用以及仓储管理管理 (仅举几例)在内部依赖 Osquery 提供的核心功能。
许多处理安全、DevOps、合规性的应用以及仓储管理管理仅举几例在内部依赖 Osquery 提供的核心功能。
### 安装 Osquery
### Install Osquery
Osquery 适用于 LinuxmacOSWindowsFreeBSD。按照[指南][4]为你的操作系统安装最新版本。(我会在下面的例子中使用 4.7.0 版本。)
Osquery 适用于 Linux、macOS、Windows、FreeBSD。请按照 [指南][4] 为你的操作系统安装最新版本。(我会在下面的例子中使用 4.7.0 版本。)
安装完成后,确保 Osquery 可以工作:
@ -44,10 +43,10 @@ $
Osquery 有两个主要组件:
* **osqueri** 是一个交互式的 SQL 查询控制台,可以独立运行,不需要超级用户权限(除非要查询的表格需要访问权限)。
* **osqueryd** 像一个安装在主机的监控守护进程,可以定期调度查询操作执行,从底层架构收集信息。
* `osqueri` 是一个交互式的 SQL 查询控制台,可以独立运行,不需要超级用户权限(除非要查询的表格需要访问权限)。
* `osqueryd` 像一个安装在主机的监控守护进程,可以定期调度查询操作执行,从底层架构收集信息。
可以在不运行 osqueryd 的情况下执行 osqueri 。另一个工具,**osqueryctl**,控制守护进程的启动,停止,并检查其状态。
可以在不运行 `osqueryd` 的情况下执行 `osqueri`。另一个工具,`osqueryctl`,控制守护进程的启动、停止,并检查其状态。
```
$ rpm -ql osquery-4.8.0-1.linux.x86_64 | grep bin
@ -59,19 +58,19 @@ $
### 使用 osqueryi 交互式命令提示符
你和 Osquery 的交互与使用 SQL 数据库十分相似。事实上osqueryi 是 SQList shell 的一个修改版。执行 `osqueryi` 命令进入交互式命令提示符 ,就可以执行 Osquery 的命令,通常以 `.` 开始:
你和 Osquery 的交互与使用 SQL 数据库十分相似。事实上,`osqueryi` 是 SQList shell 的一个修改版。执行 `osqueryi` 命令进入交互式命令提示符 ,就可以执行 Osquery 的命令,通常以 `.` 开始:
```
$ osqueryi
Using a virtual database. Need help, type '.help'
osquery>
osquery>
```
要退出交互式命令提示符,执行 `.quit` 命令回到操作系统的命令提示符:
```
osquery>
osquery> .quit
osquery>
osquery> .quit
$
```
@ -80,22 +79,22 @@ $
如前所述Osquery 像 SQL 查询一样输出数据,数据库中的信息通常保存在表中。但是如何在不知道表名的情况下查询这些表呢?你可以运行 `.tables` 命令列出所有可以查询的表。如果你是一个 Linux 长期用户或者一个系统管理员 ,就会对表名十分熟悉,因为你一直在使用操作系统命令获取同样的信息:
```
osquery> .tables
=> acpi_tables
=> apparmor_events
=> apparmor_profiles
=> apt_sources
osquery> .tables
=> acpi_tables
=> apparmor_events
=> apparmor_profiles
=> apt_sources
<< snip >>
<<裁剪>>
=&gt; arp_cache
=&gt; user_ssh_keys
=&gt; users
=&gt; yara
=&gt; yara_events
=&gt; ycloud_instance_metadata
=&gt; yum_sources
osquery&gt;
=> arp_cache
=> user_ssh_keys
=> users
=> yara
=> yara_events
=> ycloud_instance_metadata
=> yum_sources
osquery>
```
### 检查各个表的模式
@ -103,34 +102,34 @@ osquery&gt;
知道表名后,可以查看每个表提供的信息。既然 `ps` 命令经常用于获取进程信息,就以 `processes` 为例。执行 `.schema` 命令加上表名查看表中保存的信息。如果要验证命令返回的结果,可以快速执行 `ps -ef``ps aux`,对比命令的输出和表中的内容:
```
osquery&gt; .schema processes
osquery> .schema processes
CREATE TABLE processes(`pid` BIGINT, `name` TEXT, `path` TEXT, `cmdline` TEXT, `state` TEXT, `cwd` TEXT, `root` TEXT, `uid` BIGINT, `gid` BIGINT, `euid` BIGINT, `egid` BIGINT, `suid` BIGINT, `sgid` BIGINT, `on_disk` INTEGER, `wired_size` BIGINT, `resident_size` BIGINT, `total_size` BIGINT, `user_time` BIGINT, `system_time` BIGINT, `disk_bytes_read` BIGINT, `disk_bytes_written` BIGINT, `start_time` BIGINT, `parent` BIGINT, `pgroup` BIGINT, `threads` INTEGER, `nice` INTEGER, `is_elevated_token` INTEGER HIDDEN, `elapsed_time` BIGINT HIDDEN, `handle_count` BIGINT HIDDEN, `percent_processor_time` BIGINT HIDDEN, `upid` BIGINT HIDDEN, `uppid` BIGINT HIDDEN, `cpu_type` INTEGER HIDDEN, `cpu_subtype` INTEGER HIDDEN, `phys_footprint` BIGINT HIDDEN, PRIMARY KEY (`pid`)) WITHOUT ROWID;
osquery&gt;
osquery>
```
要进一步确认这一点,使用下面的命令查看 RPM 包的结构信息,然后与操作系统命令 `rpm -qa``rpm -qi` 的输出比较:
要进一步确认,可以使用下面的命令查看 RPM 包的结构信息,然后与操作系统命令 `rpm -qa``rpm -qi` 的输出比较:
```
osquery&gt;
osquery&gt; .schema rpm_packages
osquery>
osquery> .schema rpm_packages
CREATE TABLE rpm_packages(`name` TEXT, `version` TEXT, `release` TEXT, `source` TEXT, `size` BIGINT, `sha1` TEXT, `arch` TEXT, `epoch` INTEGER, `install_time` INTEGER, `vendor` TEXT, `package_group` TEXT, `pid_with_namespace` INTEGER HIDDEN, `mount_namespace_id` TEXT HIDDEN, PRIMARY KEY (`name`, `version`, `release`, `arch`, `epoch`, `pid_with_namespace`)) WITHOUT ROWID;
osquery&gt;
osquery>
```
从 Osquery 的[表格文档][5]获取更多信息。
从 Osquery 的 [表格文档][5] 获取更多信息。
### 使用 PRAGMA 命令
为了防止模式信息对你来说太难看懂,还有另一种途径能够以详细的表格格式打印表中的信息:`PRAGMA` 命令。例如,我想通过 `PRAGMA` 用一种易于理解的格式查看 `rpm_packages` 表的信息:
或许模式信息对你来说太难看懂,还有另一种途径能够以详细的表格格式打印表中的信息:`PRAGMA` 命令。例如,我想通过 `PRAGMA` 用一种易于理解的格式查看 `rpm_packages` 表的信息:
```
`osquery> PRAGMA table_info(rpm_packages);`
osquery> PRAGMA table_info(rpm_packages);
```
这种表格式信息的一个好处是你可以关注想要查询的字段,查看命令提供的类型信息:
```
osquery&gt; PRAGMA table_info(users);
osquery> PRAGMA table_info(users);
+-----+-------------+--------+---------+------------+----+
| cid | name | type | notnull | dflt_value | pk |
+-----+-------------+--------+---------+------------+----+
@ -144,7 +143,7 @@ osquery&gt; PRAGMA table_info(users);
| 7 | shell | TEXT | 0 | | 0 |
| 8 | uuid | TEXT | 1 | | 3 |
+-----+-------------+--------+---------+------------+----+
osquery&gt;
osquery>
```
### 进行你的第一次查询
@ -152,8 +151,8 @@ osquery&gt;
在你从表、模式、条目中获取到所有进行查询所需要的信息后,进行你的第一次 SQL 查询查看其中的信息。下面的查询返回系统中的用户和每个用户的用户 ID、组 ID、主目录和默认的命令行解释器。Linux 用户通过查看 `/etc/passwd` 文件的内容并执行 `grep`、`sed`、`awk` 命令获取同样的信息。
```
osquery&gt;
osquery&gt; select uid,gid,directory,shell,uuid FROM users LIMIT 7;
osquery>
osquery> select uid,gid,directory,shell,uuid FROM users LIMIT 7;
+-----+-----+----------------+----------------+------+
| uid | gid | directory | shell | uuid |
+-----+-----+----------------+----------------+------+
@ -165,12 +164,12 @@ osquery&gt; select uid,gid,directory,shell,uuid FROM users LIMIT 7;
| 5 | 0 | /sbin | /bin/sync | |
| 6 | 0 | /sbin | /sbin/shutdown | |
+-----+-----+----------------+----------------+------+
osquery&gt;
osquery>
```
### 不进入交互模式的查询
如果你想要在不进入 osqueri 交互模式的情况下进行查询,该怎么办?要用查询操作写命令行解释器脚本,这种方式可能十分有用。这种情况下,可以直接从 Bash 解释器 `echo` SQL 查询,通过管道输出到 osqueri
如果你想要在不进入 `osqueri` 交互模式的情况下进行查询,该怎么办?要用查询操作写命令行解释器脚本,这种方式可能十分有用。这种情况下,可以直接从 Bash 解释器 `echo` SQL 查询,通过管道输出到 `osqueri`
```
$ echo "select uid,gid,directory,shell,uuid FROM users LIMIT 7;" | osqueryi
@ -193,7 +192,7 @@ $
Osquery 还可以列出系统启动时开始的所有服务。例如,可以查询 `startup_items` 表获取启动时开始的前五项服务的名称、状态和路径:
```
osquery&gt; SELECT name,type,status,path FROM startup_items LIMIT 5;
osquery> SELECT name,type,status,path FROM startup_items LIMIT 5;
name = README
type = Startup Item
status = enabled
@ -218,7 +217,7 @@ status = enabled
type = Startup Item
status = enabled
path = /usr/libexec/at-spi-bus-launcher --launch-immediately
osquery&gt;
osquery>
```
### 查阅二进制文件的 ELF 信息
@ -226,7 +225,7 @@ osquery&gt;
假如你想要弄清 `ls` 二进制文件的更多细节,通常会通过 `readelf -h` 命令,加上 `ls` 命令的路径。查询 Osquery 的 `elf_info` 表你可以得到同样的信息:
```
osquery&gt; SELECT * FROM elf_info WHERE path="/bin/ls";
osquery> SELECT * FROM elf_info WHERE path="/bin/ls";
class = 64
abi = sysv
abi_version = 0
@ -236,10 +235,10 @@ abi_version = 0
entry = 24064
flags = 0
path = /bin/ls
osquery&gt;
osquery>
```
现在你应该初步了解如何使用 osqueri 查询自己想要的信息。然而,这些信息保存在数量巨大的表中;我查询过的一个系统中,有 156 个不同的表,这个数字可能是十分惊人的:
现在你应该初步了解如何使用 `osqueri` 查询自己想要的信息。然而,这些信息保存在数量巨大的表中;我查询过的一个系统中,有 156 个不同的表,这个数字可能是十分惊人的:
```
$ echo ".tables" | osqueryi | wc -l
@ -249,65 +248,57 @@ $
要让事情变得更容易,可以从这些表开始获取你的 Linux 系统的信息:
**System information table**
**系统信息表:**
```
`osquery> select * from system_info;`
osquery> select * from system_info;
```
**System limit information**
**系统限制信息:**
```
`osquery> select * from ulimit_info;`
osquery> select * from ulimit_info;
```
**Files opened by various processes**
**由各种进程打开的文件:**
```
`osquery> select * from process_open_files;`
osquery> select * from process_open_files;
```
**Open ports on a system**
**系统上开放的端口:**
```
`osquery> select * from listening_ports;`
osquery> select * from listening_ports;
```
**Running processes information**
**运行中的进程信息:**
```
`osquery> select * from processes;`
osquery> select * from processes;
```
**Installed packages information**
**已安装的包信息:**
```
`osquery> select * from rpm_packages;`
osquery> select * from rpm_packages;
```
**User login information**
**用户登录信息:**
```
`osquery> select * from last;`
osquery> select * from last;
```
**System log information**
**系统日志信息:**
```
`osquery> select * from syslog_events;`
osquery> select * from syslog_events;
```
### 了解更多
Osquery 是一个强大的工具,提供了许多可以用于解决各种使用案例的主机信息。你可以阅读[文档][6]了解更多 Osquery 的信息。
Osquery 是一个强大的工具,提供了许多可以用于解决各种使用案例的主机信息。你可以阅读 [文档][6] 了解更多 Osquery 的信息。
--------------------------------------------------------------------------------
@ -315,8 +306,8 @@ via: https://opensource.com/article/21/6/osquery-linux
作者:[Gaurav Kamathe][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/YungeG)
校对:[校对者ID](https://github.com/校对者ID)
译者:[YungeG](https://github.com/YungeG)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -3,29 +3,30 @@
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-13579-1.html)
使用这个 Python 模块输入不可见的密码
======
用 GPG 和 Python 的 getpass 模块给你的密码多一层安全保障。
![Password lock][1]
密码对程序员来说尤其成问题。你不应该在不加密的情况下存储它们,而且你也不应该在用户输入密码的时候透露出输入的内容。当我决定要提高我的笔记本电脑的安全性时,这对我来说变得特别重要。我对我的家目录进行了加密,但当我登录后,任何以纯文本形式存储在配置文件中的密码都有可能暴露在偷窥者面前
> 用 GPG 和 Python 的 getpass 模块给你的密码多一层安全保障。
具体来说,我使用一个名为 [Mutt][2] 的应用作为我的电子邮件客户端。它可以让我在我的 Linux 终端中阅读和撰写电子邮件,但通常它希望在其配置文件中有一个密码。我限制了我的 Mutt 配置文件的权限,以便只有我可以看到它,但我是我的笔记本电脑的唯一用户,所以我并不真的担心经过认证的用户会无意中看到我的配置文件。相反,我想保护自己不至于心不在焉地把我的配置发布到网上,无论是为了吹嘘还是为了版本控制,我的密码都暴露了。此外,虽然我不希望我的系统上有不受欢迎的客人,但我确实想确保入侵者不能通过对我的配置上运行 `cat` 就获得我的密码。
![](https://img.linux.net.cn/data/attachment/album/202107/14/101543fy6up6imco65mi68.jpg)
密码对程序员来说尤其重要。你不应该在不加密的情况下存储它们,而且你也不应该在用户输入密码的时候显示出输入的内容。当我决定要提高我的笔记本电脑的安全性时,这对我来说变得特别重要。我对我的家目录进行了加密,但当我登录后,任何以纯文本形式存储在配置文件中的密码都有可能暴露在偷窥者面前。
具体来说,我使用一个名为 [Mutt][2] 的应用作为我的电子邮件客户端。它可以让我在我的 Linux 终端中阅读和撰写电子邮件,但通常它希望在其配置文件中有一个密码。我限制了我的 Mutt 配置文件的权限,以便只有我可以看到它,我是我的笔记本电脑的唯一用户,所以我并不真的担心经过认证的用户会无意中看到我的配置文件。相反,我想保护自己,无论是为了吹嘘还是为了版本控制,不至于心不在焉地把我的配置发布到网上,把我的密码暴露了。此外,虽然我不希望我的系统上有不受欢迎的客人,但我确实想确保入侵者不能通过对我的配置上运行 `cat` 就获得我的密码。
### Python GnuPG
Python 模块 `python-gnupg``gpg` 应用的一个 Python 封装。该模块的名字是 `python-gnupg`,你不要把它和一个叫做 `gnupg` 的模块混淆。
[GnuPG][3]GPG 是 Linux 的默认加密系统,我从 2009 年左右开始使用它。我对它感到很舒服,对它的安全性有很高的信任。
[GnuPG][3]GPG 是 Linux 的默认加密系统,我从 2009 年左右开始使用它。我对它很熟悉,对它的安全性有很高的信任。
我决定将我的密码输入 Mutt 的最好方法是将我的密码存储在一个加密的 GPG 文件中,创建一个提示我的 GPG 密码来解锁这个加密文件,然后将密码交给 Mutt实际上是交给 `offlineimap` 命令,我用它来同步我的笔记本和电子邮件服务器)。
[用 Python 获取用户输入][4]是非常容易的。对 `input` 进行调用,无论用户输入什么,都会被存储为一个变量:
[用 Python 获取用户输入][4] 是非常容易的。对 `input` 进行调用,无论用户输入什么,都会被存储为一个变量:
```
print("Enter password: ")
@ -36,7 +37,6 @@ print("You entered: ", myinput)
我的问题是,当我根据密码提示在终端上输入密码时,我所输入的所有内容对任何从我肩膀上看过去或滚动我的终端历史的人来说都是可见的:
```
$ ./test.py
Enter password: my-Complex-Passphrase
@ -48,15 +48,12 @@ Enter password: my-Complex-Passphrase
你可以用 [pip][5] 安装这两个模块:
```
$ python -m pip install --user \
python-gnupg getpass4
$ python -m pip install --user python-gnupg getpass4
```
下面是我的 Python 脚本,用于创建密码提示:
```
#!/usr/bin/env python
# by Seth Kenlon
@ -92,7 +89,6 @@ if __name__ == "__main__":
要查看脚本的运行情况,你首先必须创建一个加密文件(我假设你已经设置了 GPG
```
$ echo "hello world" &gt; pass
$ gpg --encrypt pass
@ -102,14 +98,13 @@ $ rm pass
现在运行 Python 脚本:
```
$ python ~/.mutt/password_prompt.py
Enter your GPG password:
hello world
```
当你输入时没有任何显示,但只要你正确输入 GPG 口令,你就会看到测试信息。
当你输入时没有任何显示,但只要你正确输入 GPG 口令,你就会看到测试信息。
### 将密码提示符与 offlineimap 整合起来
@ -117,15 +112,14 @@ hello world
首先,添加一行引用 Python 文件的内容:
```
`pythonfile = ~/.mutt/password_prompt.py`
pythonfile = ~/.mutt/password_prompt.py
```
然后将 `.offlineimaprc`中的 `remotepasseval` 行改为调用 `password_prompt.py`中的 `get_api_pass()` 函数:
```
`remotepasseval = get_api_pass()`
remotepasseval = get_api_pass()
```
配置文件中不再有密码!
@ -134,7 +128,7 @@ hello world
在你的个人电脑上考虑安全问题有时会让人觉得很偏执。你的 SSH 配置是否真的需要限制为 600隐藏在名为 `.mutt` 的无关紧要的电子邮件密码真的重要吗?也许不重要。
然而,知道我没有把敏感数据悄悄地藏在我的配置文件里,使我更容易把文件提交到公共 Git 仓库,把片段复制和粘贴到支持论坛,并以实际的、已知的好的配置文件的形式分享我的知识。仅就这一点而言,安全性的提高使我的生活更加轻松。而且有这么多好的 Python 模块可以提供帮助,这很容易实现。
然而,知道我没有把敏感数据悄悄地藏在我的配置文件里,使我更容易把文件提交到公共 Git 仓库,把片段复制和粘贴到支持论坛,并以实好的配置文件的形式分享我的知识。仅就这一点而言,安全性的提高使我的生活更加轻松。而且有这么多好的 Python 模块可以提供帮助,这很容易实现。
--------------------------------------------------------------------------------
@ -143,7 +137,7 @@ via: https://opensource.com/article/21/7/invisible-passwords-python
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -2,7 +2,7 @@
[#]: via: (https://news.itsfoss.com/can-windows-11-influence-linux/)
[#]: author: (Ankush Das https://news.itsfoss.com/author/ankush/)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (zz-air)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
@ -100,7 +100,7 @@ via: https://news.itsfoss.com/can-windows-11-influence-linux/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
译者:[zz-air](https://github.com/zz-air)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,3 +1,4 @@
stevending is translating
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )

View File

@ -1,119 +0,0 @@
[#]: subject: (Encrypt and decrypt files with a passphrase on Linux)
[#]: via: (https://opensource.com/article/21/7/linux-age)
[#]: author: (Sumantro Mukherjee https://opensource.com/users/sumantro)
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
Encrypt and decrypt files with a passphrase on Linux
======
Age is a simple, easy-to-use tool that allows you to encrypt and decrypt
files with a single passphrase.
![Scissors cutting open access to files][1]
Encryption and security for protecting files and sensitive documents have long been a concern for users. Even as more and more of our data is housed on websites and cloud services, protected by user accounts with ever-more secure and challenging passwords, there's still great value in being able to store sensitive data on our own filesystems, especially when we can encrypt that data quickly and easily.
[Age][2] allows you to do this. It is a small, easy-to-use tool that allows you to encrypt a file with a single passphrase and decrypt it as required.
### Install age
Age is available to [install][3] from most Linux repositories.
To install it on Fedora:
```
`$ sudo dnf install age -y`
```
On macOS, use [MacPorts][4] or [Homebrew][5]. On Windows, use [Chocolatey][6].
### Encrypting and decrypting files with age
Age can encrypt and decrypt files with either a public key or a passphrase set by the user.
#### Using age with a public key
First, generate a public key and write the output to a `key.txt` file:
```
$ age-keygen -o key.txt
Public key: age16frc22wz6z206hslrjzuv2tnsuw32rk80pnrku07fh7hrmxhudawase896m9
```
### Encrypt with a public key
To encrypt a file with your public key:
```
`$ touch mypasswds.txt | age -r ageage16frc22wz6z206hslrjzuv2tnsuw32rk80pnrku07fh7hrmxhudawase896m9 > mypass.tar.gz.age`
```
In this example, the file `mypasswds.txt` is encrypted with the public key I generated and put inside an encrypted file called `mypass.tar.gz.age`.
### Decrypt with a public key
To decrypt the information you've protected, use the `age` command and the `--decrypt` option:
```
`$ age --decrypt -i key.txt -o mypass.tar.gz mypass.tar.gz.age`
```
In this example, age uses the key stored in `key.text` and decrypts the file I created in the previous step.
### Encrypt with a passphrase
Encrypting a file without a public key is known as symmetrical encryption. It allows a user to set the passphrase to encrypt and decrypt a file. To do so:
```
$ age --passphrase --output mypasswd-encrypted.txt mypasswd.txt
Enter passphrase (leave empty to autogenerate a secure one):  
Confirm passphrase:
```
In this example, age prompts you for a passphrase, which it uses to encrypt the input file `mypasswd.txt` and render the file `mypasswd-encrypted.txt` in return.
### Decrypt with a passphrase
To decrypt a file encrypted with a passphrase, use the `age` command with the `--decrypt` option:
```
`$ age --decrypt --output passwd-decrypt.txt mypasswd-encrypted.txt`
```
In this example, age prompts you for the passphrase, then decrypts the contents of the `mypasswd-encrypted.txt` file into `passwd-decrypt.txt`, as long as you provide the passphrase that matches the one set during encryption.
### Don't lose your keys
Whether you're using passphrase encryption or public-key encryption, you _must not_ lose the credentials for your encrypted data. By design, a file encrypted with age cannot be decrypted without the key used to encrypt it. So back up your public key, and remember those passphrases!
### Easy encryption at last
Age is a really robust tool. I like to encrypt my sensitive files, especially tax records and other archival data, into a `.tz` file for later access. Age is user-friendly and makes it very easy to get started with encryption on the go.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/7/linux-age
作者:[Sumantro Mukherjee][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/sumantro
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/document_free_access_cut_security.png?itok=ocvCv8G2 (Scissors cutting open access to files)
[2]: https://github.com/FiloSottile/age
[3]: https://github.com/FiloSottile/age#installation
[4]: https://opensource.com/article/20/11/macports
[5]: https://opensource.com/article/20/6/homebrew-mac
[6]: https://opensource.com/article/20/3/chocolatey

View File

@ -2,7 +2,7 @@
[#]: via: (https://itsfoss.com/converseen/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -0,0 +1,138 @@
[#]: subject: (Use VS Code to develop in containers)
[#]: via: (https://opensource.com/article/21/7/vs-code-remote-containers-podman)
[#]: author: (Brant Evans https://opensource.com/users/branic)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
Use VS Code to develop in containers
======
Create consistency to avoid problems when you have multiple developers
working on the same project.
![Women programming][1]
Coding and testing inconsistencies are a risk when you have multiple developers with different development environments working on a project. [Visual Studio Code][2] (VS Code) is an integrated development environment (IDE) that can help minimize these issues. It can be combined with containers to provide separate development environments for each application alongside a consistent development environment.
VS Code's [Remote - Containers extension][3] enables you to define a container, use that definition to build a container, and develop inside the container. This container definition can be checked into the source code repository along with the application code, which allows all developers to use the same definition to build and develop within a container.
By default, the Remote - Containers extension uses Docker to build and run the container, but it is easy to use [Podman][4] for container runtimes, and it enables using [rootless containers][5].
This article walks you through the setup to develop inside a rootless container using Podman with VS Code and the Remote - Containers extension.
### Initial configuration
Before continuing, ensure your Red Hat Enterprise Linux (RHEL) or Fedora workstation is updated with the latest errata and that VS Code and the Remote - Containers extension are installed. (See the [VS Code website][2] for more information on installing.)
Next, install Podman and its supporting packages with a simple `dnf install` command:
```
`$ sudo dnf install -y podman`
```
After you install Podman, configure VS Code to use the Podman executable (instead of Docker) for interacting with the container. Within VS Code, navigate to **File &gt; Preferences &gt; Settings** and click the **&gt;** icon next to **Extensions**. In the dropdown menu that appears, select **Remote - Containers**, and scroll down to find the **Remote &gt; Containers: Docker Path** option. In the text box, replace docker with **podman**.
![Enter "podman" in the text box][6]
(Brant Evans, [CC BY-SA 4.0][7])
Now that the configurations are done, create and open a new folder or an existing folder for the project in VS Code.
### Define the container
This tutorial uses the example of creating a container for Python 3 development.
The Remote - Containers extension can add the necessary basic configuration files to the project folder. To add these files, open the Command Pallet by entering **Ctrl+Shift+P** on your keyboard, search for **Remote-Containers: Add Development Container Configuration Files**, and select it.
![Remote-Containers: Add Development Container Configuration Files][8]
(Brant Evans, [CC BY-SA 4.0][7])
In the next pop-up, define the type of development environment you want to set up. For this example configuration, search for the **Python 3** definition and select it.
![Select Python 3 definition][9]
(Brant Evans, [CC BY-SA 4.0][7])
Next, select the version of Python that will be used in the container. Select the **3 (default)** option to use the latest version.
![Select the 3 \(default\) option][10]
(Brant Evans, [CC BY-SA 4.0][7])
The Python configuration can also install Node.js, but for this example, **uncheck Install Node.js** and click OK.
![Uncheck "Install Node.js"][11]
(Brant Evans, [CC BY-SA 4.0][7])
It will create a `.devcontainer` folder containing files named `devcontainer.json` and `Dockerfile`. VS Code automatically opens the `devcontainer.json` file so that you can customize it.
### Enable rootless containers
In addition to the obvious security benefits, one of the other reasons to run a container as rootless is that all the files created in the project folder will be owned by the correct user ID (UID) outside the container. To run the development container as a rootless container, modify the `devcontainer.json` file by adding the following lines to the end of it:
```
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,Z",
"workspaceFolder": "/workspace",
"runArgs": ["--userns=keep-id"],
"containerUser": "vscode"
```
These options tell VS Code to mount the Workspace with the proper SELinux context, create a user namespace that maps your UID and GID to the same values inside the container, and use `vscode` as your username inside the container. The `devcontainer.json` file should look like this (don't forget the commas at the end of the lines, as indicated):
![Updated devcontainer.json file][12]
(Brant Evans, [CC BY-SA 4.0][7])
Now that you've set up the container configuration, you can build the container and open the workspace inside it. Reopen the Command Palette (with **Ctrl+Shift+P**), and search for **Remote-Containers: Rebuild and Reopen in Container**. Click on it, and VS Code will start to build the container. Now is a great time to take a break (and get your favorite beverage), as building the container may take several minutes.
![Building the container][13]
(Brant Evans, [CC BY-SA 4.0][7])
Once the container build completes, the project will open inside the container. Files created or edited within the container will be reflected in the filesystem outside the container with the proper user permissions applied to the files. Now, you can proceed with development within the container. VS Code can even bring your SSH keys and Git configuration into the container so that committing code will work just like it does when editing outside the container.
### Next steps
Now that you've completed the basic setup and configuration, you can further enhance the configuration's usefulness. For example:
* Modify the Dockerfile to install additional software (e.g., required Python modules).
* Use a customized container image. For example, if you're doing Ansible development, you could use Quay.io's [Ansible Toolset][14]. (Be sure to add the `vscode` user to the container image via the Dockerfile.)
* Commit the files in the `.devcontainer` directory to the source code repository so that other developers can take advantage of the container definition for their development efforts.
Developing inside a container helps prevent conflicts between different projects by keeping the dependencies and code for each separate. You can use Podman to run containers in a rootless environment that increases security. By combining VS Code, the Remote - Containers extension, and Podman, you can easily set up a consistent environment for multiple developers, decrease setup time, and reduce bugs from differences in development environments in a secure fashion.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/7/vs-code-remote-containers-podman
作者:[Brant Evans][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/branic
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/collab-team-pair-programming-code-keyboard2.png?itok=WnKfsl-G (Women programming)
[2]: https://code.visualstudio.com/
[3]: https://code.visualstudio.com/docs/remote/containers
[4]: https://podman.io/
[5]: https://www.redhat.com/sysadmin/rootless-podman-makes-sense
[6]: https://opensource.com/sites/default/files/uploads/vscode-remote_podman.png (Enter "podman" in the text box)
[7]: https://creativecommons.org/licenses/by-sa/4.0/
[8]: https://opensource.com/sites/default/files/uploads/adddevelopmentcontainerconfigurationfiles.png (Remote-Containers: Add Development Container Configuration Files)
[9]: https://opensource.com/sites/default/files/uploads/python3.png (Select Python 3 definition)
[10]: https://opensource.com/sites/default/files/uploads/python3default.png (Select the 3 (default) option)
[11]: https://opensource.com/sites/default/files/uploads/unchecknodejs.png (Uncheck "Install Node.js")
[12]: https://opensource.com/sites/default/files/uploads/newdevcontainerjson.png (Updated devcontainer.json file)
[13]: https://opensource.com/sites/default/files/uploads/buildingcontainer.png (Building the container)
[14]: https://quay.io/repository/ansible/toolset

View File

@ -0,0 +1,239 @@
[#]: subject: (Use XMLStarlet to parse XML in your the Linux terminal)
[#]: via: (https://opensource.com/article/21/7/parse-xml-linux)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
Use XMLStarlet to parse XML in your the Linux terminal
======
Become an XML star with XMLStarlet, an XML toolkit for your terminal.
![Penguin with green background][1]
Learning to parse XML is often considered a complex venture, but it doesn't have to be. [XML is highly and strictly structured][2], so it's relatively predictable. There are also lots of tools out there to help make the job manageable.
One of my favorite XML utilities is [XMLStarlet][3], an XML toolkit for your terminal. With XMLStarlet, you can validate, parse, edit, format, and transform XML data. XMLStarlet is a relatively minimal command, but navigating XML is full of potential, so this article demonstrates how to use it to query XML data.
### Install
XMLStarlet is installed by default on CentOS, Fedora, and many other modern Linux distributions, so just open a terminal and type `xmlstarlet` to access it. If XMLStarlet isn't already installed, your operating system offers to install it for you.
Alternately, you can install the `xmlstarlet` command from your package manager:
```
`$ sudo dnf install xmlstarlet`
```
On macOS, use [MacPorts][4] or [Homebrew][5]. On Windows, use [Chocolatey][6].
Should all else fail, you can install it manually from the [source code on Sourceforge][7].
### Parsing XML with XMLStarlet
There are many tools designed to help parse and transform XML data, including software libraries that let you [write your own parser][8] and complex commands like `fop` and `xsltproc`. Sometimes you don't need to process XML data, though; you just need a convenient way to extract important data from, update, or just validate it. For spontaneous XML interactions, I use `xmlstarlet`, a classic "Swiss Army knife"-style application that does the most common XML tasks. You can see what it has to offer by running the command along with the `--help` option:
```
$ xmlstarlet --help
Usage: xmlstarlet [&lt;options&gt;] &lt;command&gt; [&lt;cmd-options&gt;]
where &lt;command&gt; is one of:
  ed    (or edit)      - Edit/Update XML document(s)
  sel   (or select)    - Select data or query XML document(s) (XPATH, etc)
  tr    (or transform) - Transform XML document(s) using XSLT
  val   (or validate)  - Validate XML document(s) (well-formed/DTD/XSD/RelaxNG)
  fo    (or format)    - Format XML document(s)
  el    (or elements)  - Display element structure of XML document
  c14n  (or canonic)   - XML canonicalization
  ls    (or list)      - List directory as XML
[...]
```
You can get further help by appending `--help` to the end of any of these subcommands:
```
$ xmlstarlet sel --help
  -Q or --quiet             - do not write anything to standard output.
  -C or --comp              - display generated XSLT
  -R or --root              - print root element &lt;xsl-select&gt;
  -T or --text              - output is text (default is XML)
  -I or --indent            - indent output
[...]
```
#### Selecting data with sel
You can view the data in XML with the `xmlstarlet select` (`sel` for short) command. Here's a simple XML document:
```
&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;
&lt;xml&gt;
  &lt;os&gt;
   &lt;linux&gt;
    &lt;distribution&gt;
      &lt;name&gt;Fedora&lt;/name&gt;
      &lt;release&gt;7&lt;/release&gt;
      &lt;codename&gt;Moonshine&lt;/codename&gt;
      &lt;spins&gt;
        &lt;name&gt;Live&lt;/name&gt;
        &lt;name&gt;Fedora&lt;/name&gt;
        &lt;name&gt;Everything&lt;/name&gt;
      &lt;/spins&gt;
    &lt;/distribution&gt;
    &lt;distribution&gt;
      &lt;name&gt;Fedora Core&lt;/name&gt;
      &lt;release&gt;6&lt;/release&gt;
      &lt;codename&gt;Zod&lt;/codename&gt;
      &lt;spins&gt;&lt;/spins&gt;
    &lt;/distribution&gt;
   &lt;/linux&gt;
  &lt;/os&gt;    
&lt;/xml&gt;
```
When looking for data in an XML file, your first task is to focus on the node you want to explore. If you know the path to the node, specify the full path with the `--value-of` option. The earlier in the [Document Object Model][9] (DOM) tree you start to explore, the more information you see:
```
$ xmlstarlet select --template \
\--value-of /xml/os/linux/distribution \
\--nl myfile.xml
      Fedora
      7
      Moonshine
     
        Live
        Fedora
        Everything     
     
      Fedora Core
      6
      Zod
```
The `--nl` stands for "new line," and it inserts copious amounts of whitespace to ensure your terminal prompt gets a new line after your results are in. I've removed some of the excess space in the sample output.
Narrow your focus by descending further into the DOM tree:
```
$ xmlstarlet select --template \
\--value-of /xml/os/linux/distribution/name \
\--nl myfile.xml
Fedora
Fedora Core
```
#### Conditional selects
One of the most powerful tools for navigating and parsing XML is called XPath. It governs the syntax used in XML searches and invokes functions from XML libraries. XMLStarlet understands XPath expressions, so you can make your selection conditional with an XPath function. XPath features a wealth of functions, and it's [documented in detail by W3C][10], but I find [Mozilla's XPath documentation][11] more concise.
You can use square brackets as a test function, comparing the contents of an element to some value. Here's a test for the value of the `<name>` element, which returns the release number associated only with a specific match.
Imagine for a moment that the sample XML file contains all Fedora releases beginning with 1. To view all release numbers associated with the old name "Fedora Core" (the project dropped "Core" from the name from release 7 onward):
```
$ xmlstarlet sel --template \
\--value-of '/xml/os/linux/distribution[name = "Fedora Core"]/release' \
\--nl myfile.xml
6
5
4
3
2
1
```
You could view all codenames for those releases, too, by changing the `--value-of` path to `/xml/os/linux/distribution[name = "Fedora Core"]/codename`.
### Matching paths and getting values
An advantage of viewing XML tags as nodes is that once you find the node, you can think of it as your current "directory" of data. It's not really a directory, at least not in the filesystem sense, but it is a collection of data that you can query. To help you keep your destination and the data "inside" it separate, XMLStarlet differentiates between what you're trying to match with the `--match` option and the value of the data you want with a `--value-of` option.
Suppose you know that the `<spin>` node contains several elements. That makes it your destination. Once you're there, you can use `--value-of` to specify which element you want a value for. To look at all elements, use a dot (`.`) to represent your current location:
```
$ xmlstarlet sel --template \
\--match '/xml/os/linux/distribution/spin' \
\--value-of '.' --nl myfile.xml \
Live
Fedora
Everything
```
As with navigating the DOM, you can use XPath expressions to limit the scope of what data is returned. In this example, I use the `last()` function to retrieve just the last element in the `spin` node:
```
$ xmlstarlet select --template \
\--match '/xml/os/linux/distribution/spin' \
\--value-of '*[last()]' --nl myfile.xml
Everything
```
In this example, I use the `position()` function to select a specific element in the `spin` node:
```
$ xmlstarlet select --template \
\--match '/xml/os/linux/distribution/spin' \
\--value-of '*[position() = 2]' --nl myfile.xml
Fedora
```
The `--match` and `--value-of` options can overlap, so it's up to you how you want to use them together. These two expressions, in the case of the sample XML, do the same thing:
```
$ xmlstarlet select  --template \
\--match '/xml/os/linux/distribution/spin' \
\--value-of '.' \
\--nl myfile.xml
Live
Fedora
Everything     
$ xmlstarlet select --template \
\--match '/xml/os/linux/distribution' \
\--value-of 'spin' \
\--nl myfile.xml
Live
Fedora
Everything
```
### Getting comfortable with XML
XML can seem over-verbose and unwieldy at times, but the tools built to interact with it consistently surprise me. If you're looking to take advantage of XML, then XMLStarlet could be a good entry point. The next time you're about to open an XML file to look at structured data, try using XMLStarlet and see if you can query that data instead. The more comfortable you get with XML, the better it can serve you as a robust and flexible data format.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/7/parse-xml-linux
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux_penguin_green.png?itok=ENdVzW22 (Penguin with green background)
[2]: https://opensource.com/article/21/6/what-xml
[3]: https://en.wikipedia.org/wiki/XMLStarlet
[4]: https://opensource.com/article/20/11/macports
[5]: https://opensource.com/article/20/6/homebrew-mac
[6]: https://opensource.com/article/20/3/chocolatey
[7]: http://xmlstar.sourceforge.net
[8]: https://opensource.com/article/21/6/parsing-config-files-java
[9]: https://opensource.com/article/21/6/what-xml#dom
[10]: https://www.w3.org/TR/1999/REC-xpath-19991116
[11]: https://developer.mozilla.org/en-US/docs/Web/XPath/Functions

View File

@ -0,0 +1,118 @@
[#]: subject: (Encrypt and decrypt files with a passphrase on Linux)
[#]: via: (https://opensource.com/article/21/7/linux-age)
[#]: author: (Sumantro Mukherjee https://opensource.com/users/sumantro)
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
在 Linux 上用密码加密和解密文件
======
age 是一个简单的、易于使用的工具,允许你用一个密码来加密和解密文件。
![Scissors cutting open access to files][1]
长期以来,保护文件和敏感文档的加密和安全一直是用户关心的问题。即使我们越来越多的数据被存放在网站和云服务上,并由带有越来越安全和具有挑战性的密码的用户账户来保护,但能够在我们自己的文件系统中存储敏感数据仍有很大的价值,特别是当我们能够快速和容易地加密这些数据时。
[age][2] 能让你这样做。它是一个小型的、易于使用的工具,允许你用一个密码加密一个文件,并根据需要解密。
### 安装 age
age 可以在大多数 Linux 软件库中[安装][3]。
要在 Fedora 上安装它:
```
`$ sudo dnf install age -y`
```
在 macOS 上,使用 [MacPorts][4] 或 [Homebrew][5]。在 Windows 上,使用 [Chocolatey][6]。
### 用 age 加密和解密文件
age 可以用公钥或用户设置的密码来加密和解密文件。
#### 在 age 中使用公钥
首先,生成一个公钥并写入 `key.txt` 文件:
```
$ age-keygen -o key.txt
Public key: age16frc22wz6z206hslrjzuv2tnsuw32rk80pnrku07fh7hrmxhudawase896m9
```
### 使用公钥加密
要用你的公钥加密一个文件:
```
`$ touch mypasswds.txt | age -r ageage16frc22wz6z206hslrjzuv2tnsuw32rk80pnrku07fh7hrmxhudawase896m9 > mypass.tar.gz.age`
```
在这个例子中,文件 `mypasswds.txt` 被我生成的公钥加密,放在一个叫做 `mypass.tar.gz.age` 的加密文件中。
### 用公钥解密
要解密你所保护的信息,使用 `age` 命令和 `--decrypt` 选项:
```
`$ age --decrypt -i key.txt -o mypass.tar.gz mypass.tar.gz.age`
```
在这个例子中age 使用存储在 `key.text` 中的密钥,并解密了我在上一步创建的文件。
### 使用密码加密
在没有公开密钥的情况下对文件进行加密被称为对称加密。它允许用户设置密码来加密和解密一个文件。要做到这一点:
```
$ age --passphrase --output mypasswd-encrypted.txt mypasswd.txt
Enter passphrase (leave empty to autogenerate a secure one):
Confirm passphrase:
```
在这个例子中age 提示你输入一个密码,它用这个密码对输入文件 `mypasswd.txt` 进行加密,并生成文件 `mypasswd-encrypted.txt`
### 使用密码解密
要解密一个用密码加密的文件,可以使用 `age` 命令和 `--decrypt` 选项:
```
`$ age --decrypt --output passwd-decrypt.txt mypasswd-encrypted.txt`
```
在这个例子中age 提示你输入密码,然后将 `mypasswd-encrypted.txt` 文件的内容解密为 `passwd-decrypt.txt`,只要你提供的密码与加密时设置的密码一致。
### 不要丢失你的密钥
无论你是使用密码加密还是公钥加密你都_不能_丢失加密数据的凭证。根据设计如果没有用于加密的密钥用 age 加密的文件是不能被解密的。所以,请备份你的公钥,并记住这些密码!
### 轻松实现加密
age 是一个真正强大的工具。我喜欢把我的敏感文件,特别是税务记录和其他档案数据,加密到 `.tz` 文件中以便以后访问。age 是用户友好的,使其非常容易随时加密。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/7/linux-age
作者:[Sumantro Mukherjee][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/sumantro
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/document_free_access_cut_security.png?itok=ocvCv8G2 (Scissors cutting open access to files)
[2]: https://github.com/FiloSottile/age
[3]: https://github.com/FiloSottile/age#installation
[4]: https://opensource.com/article/20/11/macports
[5]: https://opensource.com/article/20/6/homebrew-mac
[6]: https://opensource.com/article/20/3/chocolatey