Всем привет! Подготовил для вас материал по топу библиотек на Golang, которые необходимы вам при безопасной разработке приложений. Топ будет составлен лично по моему мнению, а я не являюсь сеньором-помидором Go разработчиком, так что не кидайтесь гнилыми тапками.
1. Lego
Данная библиотека выполняет функцию клиента Let's Encrypt'а и библиотеки ACME.
Возможности библиотеки:- ACME v2 RFC 8555
- Регистрация с помощью центра сертификации
- Получение сертификатов, как с нуля, так и с помощью существующего CSR
- Перевыпуск сертификата
- Отозвать сертификат:
- Надежная реализация всех задач ACME
- HTTP (http-01)
- DNS (dns-01)
- TLS (tls-alpn-01)
- Поддержка сертификата SAN
- Поставляется с несколькими дополнительными провайдерами DNS
- Custom challenge solvers
- Объединение сертификатов
- Вспомогательная функция OCSP
Установка:- Из исполняемого файла
- Docker
- Bash:
Код:
docker run goacme/lego -h
- Пакетные менеджеры
- Arch Linux -
Bash:
- ArchLinux (AUR) -
Bash:
- Debian -
Bash:
Код:
sudo
apt
install
-y lego
- Из сорцов
- Bash:
Код:
go
install
github.com/go-acme/lego/v4/cmd/lego@latest
- Bash:
Код:
git
clone git@github.com:go-acme/lego.git
cd
lego
make
# tests + doc + build
make
build
# only build
Данная библиотека имеет 2 варианта использования:
1. CLI
Далее я расскажу вам, как использовать Lego
для выпуска сертификатов:
Использовать встроенный веб-сервер
Bash:
Код:
lego --email
=
"you@example.com"
--domains
=
"example.com"
--http run
Вы найдете ваш сертификат в текущей рабочей директории, в папке
Bash:
Код:
$
ls
-1 ./.lego/certificates
example.com.crt
example.com.issuer.crt
example.com.json
example.com.key
[
maybe
more
files
for
different domains
..
.
]
Разбор значений файлов:
- - сертификат сервера (включая сертификат УЦ)
- - закрытый ключ, необходимый для сертификата сервера
Код:
example.com.issuer.crt
- сертификат удостоверяющего центра
- - содержит некоторую метаинформацию в кодировке JSON
Использовать DNS провайдеров
Если вы не можете использовать веб сервер, то у вас есть возможность использовать DNS провайдеров. В Lego поддерживается достаточно большое количество DNS провайдеров и вы сами можете выбрать, каким из них пользоваться. Для примеру покажу, как использовать Cloudflare для вашего домена:
Bash:
Код:
CLOUDFLARE_EMAIL
=
"you@example.com"
\
CLOUDFLARE_API_KEY
=
"yourprivatecloudflareapikey"
\
lego --email
"you@example.com"
--dns cloudflare --domains
"example.org"
run
Использовать кастомный запрос на подпись сертификата
Первый шаг в процессе получения сертификатов включает в себя создание запроса на подписание. Этот CSR содержит различную информацию, включая имя (имена) домена и открытый ключ. По умолчанию lego скроет от вас этот шаг, но если у вас уже есть CSR, вы можете легко использовать его повторно:
Bash:
Код:
lego --email
=
"you@example.com"
--http --csr
=
"/path/to/csr.pem"
run
Lego сделает вывод о доменах, подлежащих проверке, на основе содержимого CSR, поэтому убедитесь, что общее имя CSR и необязательные SubjectAltNames установлены правильно.
Использовать уже существующий веб сервер
Если у вас уже есть работающий веб сервер на 80 порту, вам нужно добавить
к аргументу
. Это действие просто записывает токен вызова http-01 в указанный каталог в папку .well-known/acme-challenge и не запускает сервер. Для завершения проверки, директория должна быть / и доступна публично. Далее Lego запишет файл токенов с ключом авторизации HTTP-01 challenge в
Код:
/.well-known/acme-challenge/
. Для этого выполните следующую команду:
Bash:
Код:
lego --accept-tos --email you@example.com --http --http.webroot /path/to/webroot --domains example.com run
Использовать скрипты
Вы можете легко подключиться к процессу получения сертификата, указав путь к скрипту:
Bash:
Код:
lego --email
=
"you@example.com"
--domains
=
"example.com"
--http run --run-hook
=
"./myscript.sh"
И давайте объясню используемые переменные:
- - электронная почта аккаунта
- - основной домен сертификата
- - путь к сертификату
- - путь к ключу сертификата
Теперь я вам расскажу вам как пользоваться ей
для обновления сертификатов:
Использовать встроенный веб сервер
По умолчанию и в соответствии с классической практикой сертификат обновляется только в том случае, если срок его действия истекает менее чем через 30 дней.
Bash:
Код:
lego --email
=
"you@example.com"
--domains
=
"example.com"
--http renew
Если сертификат нужно перевыпустить ранее, вы можете указать количество дней за сколько выпустить его.
Bash:
Код:
lego --email
=
"you@example.com"
--domains
=
"example.com"
--http renew --days
45
Использовать DNS провайдера
Ранее я уже освещал о возможностях Lego в этом направлении, если что-то не понятно, то советую перечитать информацию выше)
Bash:
Код:
CLOUDFLARE_EMAIL
=
"you@example.com"
\
CLOUDFLARE_API_KEY
=
"yourprivatecloudflareapikey"
\
lego --email
"you@example.com"
--dns cloudflare --domains
"example.org"
renew
Использовать скрипты
Bash:
Код:
lego --email
=
"you@example.com"
--domains
=
"example.com"
--http renew --renew-hook
=
"./myscript.sh"
Автоматический перевыпуск сертификата:
Очень заманчиво создать таск в cron (или таймер systemd) для автоматического обновления всех ваших сертификатов.
При этом следует учитывать, что некоторые настройки cron по умолчанию будут создавать ощутимую нагрузку на инфраструктуру провайдера ACME. В частности, задания
запускаются в полночь.
Пример оптимизированного таска для cron
Bash:
Код:
# avoid:
#@daily /usr/bin/lego ... renew
#@midnight /usr/bin/lego ... renew
#0 0 * * * /usr/bin/lego ... renew
# instead, use a randomly chosen time:
35
3
* * * /usr/bin/lego
..
. renew
Если вы используете
, то вот пример конфиг файла для вас:
Bash:
Код:
[
Unit
]
Description
=
Renew certificates
[
Timer
]
Persistent
=
true
# avoid:
#OnCalendar=*-*-* 00:00:00
#OnCalendar=daily
# instead, use a randomly chosen time:
OnCalendar
=
*-*-*
3
:35
# add extra delay, here up to 1 hour:
RandomizedDelaySec
=
1h
[
Install
]
WantedBy
=
timers.target
2. Второй вариант использования Lego, напрямую как библиотеки
Правильный, но неполный пример использования пакета acme:
Код:
Код:
package main
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"log"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
)
// You'll need a user or account type that implements acme.User
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func main() {
// Create a user. New accounts need an email and private key to start.
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal(err)
}
myUser := MyUser{
Email: "you@yours.com",
key: privateKey,
}
config := lego.NewConfig(&myUser)
// This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
config.CADirURL = "http://192.168.99.100:4000/directory"
config.Certificate.KeyType = certcrypto.RSA2048
// A client facilitates communication with the CA server.
client, err := lego.NewClient(config)
if err != nil {
log.Fatal(err)
}
// We specify an HTTP port of 5002 and an TLS port of 5001 on all interfaces
// because we aren't running as root and can't bind a listener to port 80 and 443
// (used later when we attempt to pass challenges). Keep in mind that you still
// need to proxy challenge traffic to port 5002 and 5001.
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "5002"))
if err != nil {
log.Fatal(err)
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "5001"))
if err != nil {
log.Fatal(err)
}
// New users will need to register
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
log.Fatal(err)
}
myUser.Registration = reg
request := certificate.ObtainRequest{
Domains: []string{"mydomain.com"},
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
log.Fatal(err)
}
// Each certificate comes back with the cert bytes, the bytes of the client's
// private key, and a certificate URL. SAVE THESE TO DISK.
fmt.Printf("%#v\n", certificates)
// ... all done.
}
Далее описывать функции библиотеки = переписать документацию. Так что приглашаю самим ознакомиться с ней.
2. zap
Обратите внимание, что zap поддерживает только две последние версии Go.
Zap - сверхбыстрое, структурированное, уровневое логгирование в Go
Установка
Bash:
Код:
go get -u go.uber.org/zap
Использование
В ситуациях, когда производительность важна, но не критична, используйте SugaredLogger. Он в 4-10 раз быстрее других пакетов структурированного протоколирования и включает в себя как структурированный, так и printf-стиль API.
Код:
Код:
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)
Если важны производительность и безопасность типов, используйте Logger. Он даже быстрее, чем SugaredLogger, и выделяет гораздо меньше ресурсов, но поддерживает только структурированное логгирование.
Код:
Код:
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
Для приложений, которые ведут журнал realtime, сериализация на основе отражения и форматирование строк непомерно дороги - они сильно нагружают процессор и делают много небольших выделений. Другими словами, использование
и
для регистрации тонн
s делает ваше приложение непростительно медленным.
Zap использует другой подход. Он включает кодировщик JSON без отражений, с нулевым распределением, а базовый логгер стремится избегать накладных расходов на сериализацию и выделения, где это возможно. Создавая на этой основе высокоуровневый SugaredLogger, zap позволяет пользователям выбирать, когда им нужно считать каждое выделение, а когда они предпочитают более привычный, свободно типизированный API.
По оценкам собственного пакета бенчмарков,
zap не только более производителен, чем аналогичные пакеты структурированного логгирования,
но и быстрее, чем стандартная библиотека.
3. gosec
Данная библиотека проверяет исходный код на наличие проблем безопасности путем сканирования Go AST (Abstract Syntax Tree).
Установка порадует DevSecOps
CI установка
Bash:
Код:
curl
-sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh
|
sh
-s -- -b
$(go env GOPATH)
/bin vX.Y.Z
curl
-sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh
|
sh
-s vX.Y.Z
# для Alpine Linux, где по умолчанию нет curl
wget
-O - -q https://raw.githubusercontent.com/securego/gosec/master/install.sh
|
sh
-s vX.Y.Z
gosec --help
GitHub Action
Git:
Код:
name: Run Gosec
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
tests:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v3
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
args: ./...
Локальная установка
Go 1.16+
Код:
Код:
go install github.com/securego/gosec/v2/cmd/gosec@latest
Go version < 1.16
Код:
Код:
go get -u github.com/securego/gosec/v2/cmd/gosec
Использование
Gosec может быть настроен на выполнение только групп правил, исключение определенных путей к файлам и создание отчетов в различных форматах. По умолчанию все правила будут выполняться по предоставленным входным файлам. Для рекурсивного сканирования из текущего каталога в качестве входного аргумента можно указать
Доступные правила аудита
- G101: Look for hard coded credentials
- G102: Bind to all interfaces
- G103: Audit the use of unsafe block
- G104: Audit errors not checked
- G106: Audit the use of ssh.InsecureIgnoreHostKey
- G107: Url provided to HTTP request as taint input
- G108: Profiling endpoint automatically exposed on /debug/pprof
- G109: Potential Integer overflow made by strconv.Atoi result conversion to int16/32
- G110: Potential DoS vulnerability via decompression bomb
- G111: Potential directory traversal
- G112: Potential slowloris attack
- G113: Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772)
- G114: Use of net/http serve function that has no support for setting timeouts
- G201: SQL query construction using format string
- G202: SQL query construction using string concatenation
- G203: Use of unescaped data in HTML templates
- G204: Audit use of command execution
- G301: Poor file permissions used when creating a directory
- G302: Poor file permissions used with chmod
- G303: Creating tempfile using a predictable path
- G304: File path provided as taint input
- G305: File traversal when extracting zip/tar archive
- G306: Poor file permissions used when writing to a new file
- G401: Detect the usage of DES, RC4, MD5 or SHA1
- G402: Look for bad TLS connection settings
- G403: Ensure minimum RSA key length of 2048 bits
- G404: Insecure random number source (rand)
- G501: Import blocklist: crypto/md5
- G502: Import blocklist: crypto/des
- G503: Import blocklist: crypto/rc4
- G504: Import blocklist: net/http/cgi
- G505: Import blocklist: crypto/sha1
- G601: Implicit memory aliasing of items from a range statement
Выбор правил аудита
По умолчанию gosec будет выполнять все правила по указанным путям к файлам. Однако можно выбрать группы правил для запуска с помощью флага
или указать группы правил для явного исключения с помощью флага -exclude=.
Bash:
Код:
# Запуситить конкретные правила
$ gosec -include
=
G101,G203,G401 ./
..
.
# Использовать все правила, кроме G303
$ gosec -exclude
=
G303 ./
..
.
CWE Mapping
Это уже порадует безопасников, т.к. каждая проблема соотноситься с CWE (Common Weakness Enumeration), которая описывает уязвимость.
Исключения:
Исключение тестовых файлов и папок при аудите
gosec будет игнорировать тестовые файлы всех пакетов и любых зависимостей в вашем каталоге.
Сканирование тестовых файлов может быть включено с помощью следующего флага:
Код:
Также можно исключить дополнительные папки следующим образом:
Код:
Код:
gosec -exclude-dir=rules -exclude-dir=cmd ./...
Исключение сгенерированных файлов
gosec может игнорировать сгенерированные go-файлы с комментарием сгенерированного кода по умолчанию.
Код:
// Code generated by some generator DO NOT EDIT.
Код:
Код:
gosec -exclude-generated ./...
Сохранение результатов
В настоящее время
gosec поддерживает форматы вывода text, json, yaml, csv, sonarqube, JUnit XML, html и golint. По умолчанию результаты выводятся на stdout(т.е. в консоль), но также могут быть записаны в файл. Формат вывода контролируется флагом -fmt, а имя файла устанавливается флагом -out следующим образом:
Bash:
Код:
# Запись результатов в json в файл results.json
$ gosec -fmt
=
json -out
=
results.json *.go
Также вы можете сохранить результат и в файлы, и вывести в консоль:
Bash:
Код:
$ gosec -fmt
=
json -out
=
results.json -stdout *.go
4. Hydra
Ory Hydra - это усиленный, сертифицированный OpenID OAuth 2.0 сервер и провайдер OpenID Connect, оптимизированный для низкой задержки, высокой пропускной способности и низкого потребления ресурсов. Ory Hydra не является провайдером идентификации (регистрация пользователя, вход пользователя, поток сброса пароля), а подключается к существующему провайдеру идентификации через приложение для входа и согласия.
Ory Hydra может использовать Ory Kratos в качестве сервера идентификации.
Ory Hydra - это серверная реализация системы авторизации OAuth 2.0 и OpenID Connect Core 1.0. Существующие реализации OAuth2 обычно поставляются в виде библиотек или SDK, таких как node-oauth2-server или Ory Fosite, или в виде полнофункциональных решений идентификации с управлением пользователями и пользовательскими интерфейсами, таких как Keycloak. Внедрение и использование OAuth2 без понимания всей спецификации является сложной задачей и чревато ошибками, даже если используются SDK. Основная цель Ory Hydra - сделать OAuth 2.0 и OpenID Connect 1.0 более доступными.
Самых крупные компании, использующие Hydra вы можете увидеть здесь.
Начнём с установки. Есть 2 стула:
- Docker - установка займет 5 минут. Гайд тут.
- Для настоящих мужчин
Bash:
Код:
# Linux
bash
<
(
curl
https://raw.githubusercontent.com/ory/meta/master/install.sh
)
-b
.
ory
sudo
mv
./ory /usr/local/bin/
# MacOS
brew
install
ory/tap/cli
Далее создаем проект:
Код:
Код:
ory create project --name "Ory Hydra 2.0 Example"
project_id="{set to the id from output}"
OAuth 2.0 Client Credentials / Machine-to-Machine
Создайте клиент OAuth 2.0 и запустите процесс OAuth 2.0 Client Credentials:
Bash:
Код:
ory create oauth2-client --project
$project_id
\
--name
"Client Credentials Demo"
\
--grant-type client_credentials
client_id
=
"{set to client id from output}"
client_secret
=
"{set to client secret from output}"
ory perform client-credentials --client-id
=
$client_id
--client-secret
=
$client_secret
--project
$project_id
access_token
=
"{set to access token from output}"
ory introspect token
$access_token
--project
$project_id
OAuth 2.0 Authorize Code + OpenID Connect
Bash:
Код:
ory create oauth2-client --project
$project_id
\
--name
"Authorize Code with OpenID Connect Demo"
\
--grant-type authorization_code,refresh_token
\
--response-type code
\
--redirect-uri http://127.0.0.1:4446/callback
code_client_id
=
"{set to client id from output}"
code_client_secret
=
"{set to client secret from output}"
ory perform authorization-code
\
--project
$project_id
\
--client-id
$code_client_id
\
--client-secret
$code_client_secret
code_access_token
=
"{set to access token from output}"
ory introspect token
$code_access_token
--project
$project_id
5. TFSec
tfsec использует статический анализ кода terraform для выявления возможных мисконфигов.
Начнем с установки
Установка с помощью brew/linuxbrew
Код:
Установка с помощью Chocolatey
Код:
Установка с помощью Scoop
Код:
Установка в Linux:
Код:
Код:
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash
Также вы можете скачать бинарь с releases page.
Также вы можете установить из исходников с помощью Go:
Код:
Код:
go install github.com/aquasecurity/tfsec/cmd/tfsec@latest
Использование
Тут довольно всё просто)
tfsec будет сканировать указанный каталог. Если каталог не указан, будет использоваться текущий рабочий каталог.
Bash:
Использовать через Docker
В качестве альтернативы установке и запуску tfsec на вашей системе, вы можете запустить tfsec в контейнере Docker:
Название образаОбразОписаниеaquasec/tfsecalpineОбычный tfsec образaquasec/tfsec-alpinealpineТочно так же, как aquasec/tfsec, но для тех, кто любит ясность.aquasec/tfsec-cialpinetfsec без entrypoint- полезно для сборок CI, где вы хотите переопределить командуaquasec/tfsec-scratchscratchОбраз, созданный с нуля - ничего лишнего, просто работает tfsec
Bash:
Код:
docker run --rm -it -v
"$(pwd):/src"
aquasec/tfsec /src
Использование через Github Actions
Git:
Код:
name: tfsec-pr-commenter
on:
pull_request:
jobs:
tfsec:
name: tfsec PR commenter
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Clone repo
uses: actions/checkout@master
- name: tfsec
uses: aquasecurity/tfsec-pr-commenter-action@v1.2.0
with:
github_token: ${{ github.token }}
Я надеюсь вам будет полезна эта статья. Если вас больше интересного контента от меня, то предлагаю подписаться на мой канал в telegram Дневник Безопасника 🛡