diff --git a/.drone.yml b/.drone.yml index d97bc5e..92ecbc7 100755 --- a/.drone.yml +++ b/.drone.yml @@ -10,12 +10,17 @@ steps: volumes: - name: site path: /site + - name: site-st1tru + path: /site-st1tru commands: - pip install -U -r ./requirements.txt - mkdocs build - cp -r site/ /site + - cp -r site/ /site-st1tru - chown 1000:1000 /site + - chown 1000:1000 /site-st1tru - chmod -R 777 /site + - chmod -R 777 /site-st1tru when: event: push branch: main @@ -53,4 +58,7 @@ steps: volumes: - name: site host: - path: /opt/appdata/mkdocswiki \ No newline at end of file + path: /opt/appdata/mkdocswiki +- name: site-st1tru + host: + path: /opt/appdata/nginx/st1t.ru \ No newline at end of file diff --git a/docs/blog/index.md b/docs/blog/index.md new file mode 100644 index 0000000..1050001 --- /dev/null +++ b/docs/blog/index.md @@ -0,0 +1 @@ +asd \ No newline at end of file diff --git a/docs/blog/posts/traefik-fa.md b/docs/blog/posts/traefik-fa.md new file mode 100644 index 0000000..a3eed88 --- /dev/null +++ b/docs/blog/posts/traefik-fa.md @@ -0,0 +1,382 @@ +# Руководство по Traefik Forward Auth – Простая защита через Google SSO + +![](https://st1t.ru/wp-content/uploads/2022/11/traefik-forward-auth-google-flow-840x525.png) + +---------- + +Хотите защитить свой стек Docker чем-то более надежным, чем обычная HTTP-аутентификация? Google OAuth2 SSO с Traefik Forward Auth — ваш выбор. + +Я был очень удивлен, узнав, что образ Thomseddon [Traefik Forward Auth](https://github.com/thomseddon/traefik-forward-auth) может защитить мои службы в Docker. Этот образ обеспечивает вход и аутентификацию OAuth/SSO для обратного прокси-сервера Traefik с использованием Traefik. + +> Почему Traefik Google OAuth2 для служб Docker? +> +> Google OAuth2 позволяет вам использовать свою учетную запись Google для входа в свои службы. Использование **Google OAuth с Traefik** позволит вам добавлять учетные записи в белый список, внедрять двухфакторную аутентификацию Google, а также обеспечивать единый вход (SSO) для ваших служб. Это не только обеспечивает удобство, поскольку вам не нужно часто входить в систему, но и повышает безопасность. + +Добавление Traefik OAuth2 для ваших служб Docker будет простым шагом и важным дополнением к вашему стеку Docker Traefik. + + +## НАСТРОЙКА TRAEFIK FORWARD AUTH ПРИ ПОМОЩИ GOOGLE OAUTH2 + +Добавление базовой аутентификации, предоставляемой Traefik, — это самый простой способ защитить ваш Docker и другие службы. + +В нашем предыдущем руководстве мы рассмотрели, как использовать учетные данные для входа .htpasswd и промежуточное ПО **Traefik auth middleware** для добавления базовой аутентификации с использованием меток. + +Для одной службы это может быть полезно, но это быстро становится неудобным и утомительным, когда приходится входить в несколько служб и для каждого сеанса браузера. + +После внедрения **Traefik forward authentication** теперь нужно войти в систему только один раз. И внедрив _Traefik OAuth2 с Google_, можно добавить двухфакторную аутентификацию (2FA), что делает этот метод намного более безопасным и удобным, чем использование обычной аутентификации. + +Если вы предпочитаете частную self-hosted систему многофакторной аутентификации (а не полагаться на Google), обратите внимание на Authelia или Keycloak. Я использовал Authelia для ранее, а сейчас перешел на Keyсloak для управления несколькими пользователями. Traefik OAuth2 я использую для домашних проектов. + +> ### Что такое OAuth? +> +> **OAuth** — открытый протокол (схема) [авторизации](https://ru.wikipedia.org/wiki/%D0%90%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F "Авторизация"), обеспечивающий предоставление третьей стороне ограниченный доступ к защищённым ресурсам пользователя без передачи ей (третьей стороне) логина и пароля [– Wikipedia](https://ru.wikipedia.org/wiki/OAuth) + +Прежде чем настраивать Traefik Forward Auth с Google OAuth2, давайте посмотрим, как все это сочетается друг с другом. + +### Как работает Google OAuth2 с Traefik? + +Вход и аутентификация Google OAuth для Traefik действует как посредник для ваших служб, разрешая или запрещая доступ после проверки авторизованного файла cookie в вашем браузере. Подводя итог, процесс выглядит примерно так: + +1. Для нашего хоста сделан **запрос** (например, https://traefik.example.com) +2. Запрос направляется нашим провайдером DNS на наш IP-адрес WAN, где порты 80 и 443 перенаправляются в контейнер Traefik. +3. Traefik видит входящий запрос и распознает, что **Forward Auth** определен в **метках** для этого хоста, поэтому запрос перенаправляется в контейнер **Traefik Forward Auth**. +4. Затем контейнер проверяет, есть ли в браузере авторизованный файл cookie. Если файл cookie отсутствует, запрос отправляется на **сервер авторизации Google OAuth2**. +5. После успешного входа в Google запрос отправляется на **URI перенаправления**, указанный для **веб-приложения** (https://oauth.example.com/_oauth). +6. Затем авторизованный файл cookie сохраняется в браузере, и пользователь отправляется во внутреннюю службу. + +В следующий раз, когда этот браузер попытается получить доступ к службе, защищенной входом и аутентификацией на основе OAuth, файл cookie будет распознан, и пользователь будет перенаправлен на их службу без запроса на вход! + +![](https://st1t.ru/wp-content/uploads/2022/11/traefik-forward-auth-google-flow-1024x654.png) + +Этот процесс происходит очень быстро, и как только ваш браузер получит файл cookie, вы забудете, что даже включили Google OAuth с Traefik! + +**Примечание.** Образ Traefik Forward Auth использует [**OpenID** **Connect**](https://en.wikipedia.org/wiki/OpenID_Connect) (**OIDC**),который представляет собой уровень аутентификации поверх протокола [OAuth 2.0](https://en.wikipedia.org/wiki/OAuth#OAuth_2.0 "OAuth"). Образ Docker, представленный в этом руководстве, поддерживает Google, а также [других поставщиков OIDC](https://github.com/thomseddon/traefik-forward-auth/wiki/Provider-Setup). + +Позаботившись об основах, давайте перейдем к настройке прямой аутентификации Google OAuth Traefik для наших сервисов Docker. + +> ### Как настроить OAuth? +> +> Настройка Google OAuth для Docker с помощью Traefik включает в себя 3 этапа: +> +> 1. создание записей DNS, +> 2. настройку службы Google OAuth2 и +> 3. изменение файлов компоновки Docker и добавление меток Traefik для активации прямой аутентификации. + +Итак, во-первых, нам нужно настроить службу Traefik OAuth2. Давайте настроим все предварительные условия сейчас: + +### Шаг 1. Создайте записи DNS + +Начните с создания новой DNS-записи CNAME для нашей службы OAuth (Google перенаправит на этот адрес после аутентификации). В этом руководстве мы будем использовать доменное имя **example.com**. + +Установите запись DNS как **oauth.example.com**. На рисунках ниже показан скриншот из Cloudflare. В зависимости от вашего провайдера DNS, для вас все может выглядеть по-разному, но по сути иметь одно и то же содержание. + +![](https://st1t.ru/wp-content/uploads/2022/11/01-clouldflare-dns-for-google-oauth-1024x367.png) + +Обратите внимание, что для распространения и активации записей DNS может потребоваться несколько часов. + +В качестве альтернативы, если вы включили запись CNAME с подстановочными знаками, указывающую на ваш корневой домен, вы можете пропустить этот шаг. + +### Шаг 2. Настройте службу Google OAuth2 + +Создав записи DNS, давайте перейдем к настройке Google OAuth. + +#### Шаг 2.1. Создайте проект Google. + +Нам нужно создать **проект Google**, который будет содержать наше **веб-приложение**, **экран согласия** и **учетные данные**. + +Перейдите в [Google Cloud Developers Console](https://console.developers.google.com/) и убедитесь, что вы вошли в правильный аккаунт Google, который хотите использовать (обычно это будет ваш адрес электронной почты). + +**Примечание.** Выйдите из других активных аккаунтов Google, чтобы убедиться, что на каждом этапе используется правильный аккаунт. + +При появлении запроса вам нужно будет согласиться с **Условиями использования Google Cloud Platform**, чтобы использовать их API. + +Сервис OAuth от Google можно использовать бесплатно, поэтому пока мы можем **отказаться** от бесплатной пробной версии. Нажмите «**Select a project**» и «**New project**». + +![](https://st1t.ru/wp-content/uploads/2022/11/02-google-cloud-oauth-create-new-project-1024x498.png) + +Введите уникальное имя для идентификации проекта, например **“Traefik Authentication”**. Нажмите **Create**. + +![](https://st1t.ru/wp-content/uploads/2022/11/03-google-cloud-oauth-new-project-details.png) + +#### Шаг 2.2. Создайте учетные данные OAuth + +Теперь, когда наш проект создан, нам нужно создать идентификатор клиента и секрет клиента, чтобы пройти аутентификацию в Google. Выберите наш проект **Traefik Authentication** и в меню навигации выберите **APIs & Services > Credentials**. Нажмите **Create Credentials > OAuth client ID**. + +![](https://st1t.ru/wp-content/uploads/2022/11/04-google-cloud-oauth-create-oauth-client-id.png) + +#### Шаг 2.3: Настройте Consent Screen + +После того, как вы нажмете Идентификатор клиента OAuth, вы увидите примечание о настройке consent screen, как показано ниже. Перед продолжением необходимо настроить consent screen. + +После того, как вы нажмете **OAuth Client ID**, вы увидите примечание о настройке consent screen, как показано ниже. Перед продолжением необходимо настроить consent screen. + +![](https://st1t.ru/wp-content/uploads/2022/11/05-google-cloud-oauth-configure-consent-screen.png) + +Если автоматический запрос не появится, выберите **OAuth consent screen** на левой панели. + +Далее выберите тип пользователей приложения. Выбираем тип **External** и нажимаем **Create**. + +![](https://st1t.ru/wp-content/uploads/2022/11/06-google-cloud-oauth-consent-screen-type.png) + +Выберите имя для своего приложения, например **Traefik Auth**, затем в разделе **Authorized domains** введите свой домен, например **example.com**. Убедитесь, что вы нажимаете **Enter**, чтобы добавить его, а затем нажмите **Save**. + +![](https://st1t.ru/wp-content/uploads/2022/11/07-google-cloud-oauth-consent-screen.png) + +После нажатия кнопки **Save** вы перейдете на следующий шаг. Везде нажимаем снизу **Save and Continue**. + +#### **Шаг 2.4. Создайте идентификатор клиента OAuth.** + +Выберите наш проект **Traefik Authentication** и в меню навигации выберите **APIs & Services > Credentials**. Нажмите **Create Credentials > OAuth client ID**. + +Теперь выберите тип **Web Application** и введите имя для своего веб-приложения, например, **Traefik**. Кроме того, вам потребуется ввести **Authorized redirect URI** в виде _https://oauth.example.com/_oauth_. Убедитесь, что вы нажимаете **Enter**, чтобы добавить его, а затем нажмите **Save**. + +**Примечание.** Вам разрешено добавлять только **URI перенаправления**, которые ведут на ваши **авторизованные домены**. Вернитесь к экрану согласия OAuth, если вам нужно их отредактировать. + +![](https://st1t.ru/wp-content/uploads/2022/11/08-oauth-authorized-redirect-uris.png) + +Учетные данные для нашего единого входа для Docker созданы! Скопируйте и сохраните **client ID** и **client secret**; нам нужно будет использовать их на следующем шаге. + +![](https://st1t.ru/wp-content/uploads/2022/11/09-oauth-client-id-and-secret.png) + +### Шаг 3. Настройте прямую аутентификацию Traefik с помощью OAuth2 + +Теперь, когда учетные данные OAuth настроены, осталось настроить контейнер OAuth. Войдите на свой локальный компьютер или используйте SSH-клиен для удаленного входа. + +Обязательно остановите Traefik (при необходимости) и отредактируйте файл docker-compose, добавив метки Traefik и контейнер OAuth, как описано ниже. + +Предполагается, что вы уже прочитали и выполнили большую часть моего руководства по Traefik 2 и читаете этот пост только для того, чтобы внедрить Google OAuth. + +#### Шаг 3.1. Создайте промежуточное ПО Traefik Auth и цепочку + +Давайте теперь укажем промежуточное ПО для аутентификации Traefik для OAuth2. Создайте новый файл middlewares-oauth.yml и добавьте следующие строки: +```yaml +http: + middlewares: + middlewares-oauth: + forwardAuth: + address: "http://oauth:4181" # Make sure you have the OAuth service in docker-compose.yml + trustForwardHeader: true + authResponseHeaders: + - "X-Forwarded-User" +``` +Кроме того, давайте создадим новую цепочку промежуточного программного обеспечения для сервисов, которые будут использовать Google OAuth. Откройте файл **middleware-chains.yml**, созданный в моем руководстве по Traefik, и добавьте следующие строки ниже того, что уже есть: +```yaml +http: + middlewares: + chain-oauth: + chain: + middlewares: + - middlewares-rate-limit + - middlewares-https-redirectscheme + - middlewares-secure-headers + - middlewares-oauth + - middlewares-compress +``` +**Примечание:** Промежуточное ПО для ограничения скорости, перенаправления HTTPS, заголовков безопасности и сжатия должно быть определено в соответствии с моим руководством Traefik. В противном случае Traefik не запустится. + +Сохраните файлы и выйдите из редактирования. + +#### Шаг 3.2: Добавьте секреты прямой аутентификации Traefik + +Вместо того, чтобы создавать несколько секретов, мы создадим один секретный файл для прямой аутентификации Traefik, который будет содержать все учетные данные. + +Создайте файл с именем **traefik_forward_auth** в папке **secrets** ($DOCKERDIR\secrets, если ваша установка основана на моих руководствах) и добавьте в него следующее содержимое: +``` +providers.google.client-id=yourGOOGLEclientID +providers.google.client-secret=yourCLIENTsecret +secret=yourOAUTHsecret +whitelist=yourEMAILaddress1 +whitelist=yourEMAILaddress2 +``` +Настройте вышеуказанное, используя информацию ниже: + +- **yourGOOGLEclientID** и **yourCLIENTsecret**: полученные ранее в этом руководстве по Traefik Oauth2. +- **yourOAUTHsecret**: используется для подписи файла cookie и должен быть случайным. Создайте случайный секрет с помощью: +`openssl rand -hex 16` + + +Кроме того, вы можете использовать [онлайн-сервис, подобный этому](https://www.browserling.com/tools/random-string), для создания случайного секрета. + +![](https://st1t.ru/wp-content/uploads/2022/11/10-random-secret.png) + +- **yourEMAILAddress1**: идентификатор электронной почты Google, который будет использоваться для аутентификации. При желании вы можете добавить дополнительные адреса электронной почты, которым разрешено проходить аутентификацию (например, **yourEMAILAddress2**; удалите эту строку, если вы хотите разрешить только один идентификатор электронной почты). + +Сохранить и выйти. + +Обратите внимание, что папка **secrets** и файл **traefik_forward_auth** должны иметь разрешение **600** и принадлежать пользователю **root**. + +Далее давайте настроим контейнер OAuth Forwarder. + +#### Шаг 3.3: Добавляем OAuth Forwarder контейнер + +Откройте файл docker-compose, который был создан на основе нашего предыдущего руководства по Traefik 2, и добавьте в него следующее. + +# Google OAuth - Single Sign On using OAuth 2.0 +```yaml +version: '3.7' +services: + oauth: + container_name: oauth + image: thomseddon/traefik-forward-auth:latest + restart: unless-stopped + security_opt: + - no-new-privileges:true + environment: + - CONFIG=/config + - COOKIE_DOMAIN=$DOMAINNAME_CLOUD_SERVER + - INSECURE_COOKIE=false + - AUTH_HOST=oauth.$DOMAINNAME_CLOUD_SERVER + - URL_PATH=/_oauth + - LOG_LEVEL=info + - LOG_FORMAT=text + - LIFETIME=86400 # 1 day + - DEFAULT_ACTION=auth + - DEFAULT_PROVIDER=google + secrets: + - source: traefik_forward_auth + target: /config + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.oauth-rtr.tls=true" + - "traefik.http.routers.oauth-rtr.entrypoints=https" + - "traefik.http.routers.oauth-rtr.rule=Host(`oauth.$DOMAINNAME_CLOUD_SERVER`)" + ## Middlewares + - "traefik.http.routers.oauth-rtr.middlewares=chain-oauth@file" + ## HTTP Services + - "traefik.http.routers.oauth-rtr.service=oauth-svc" + - "traefik.http.services.oauth-svc.loadbalancer.server.port=4181" +``` +**$DOMAINNAME_CLOUD_SERVER** = имя вашего домена в файле .env + +Обратите внимание, что мы используем цепочку промежуточного программного обеспечения аутентификации Traefik (**chain-oauth**) для аутентификации вместо базовой аутентификации. Используйте правильный образ для архитектуры вашей системы. + +Вы также можете изменить продолжительность (**LIFETIME**), в течение которой аутентификация действительна, с 1 дня, указанного в секундах, на другую продолжительность. Сначала установите **LOG_LEVEL** для **trace** или **debug**. Когда все заработает, вы можете изменить его на **warn**. + +При желании остальные переменные среды, определенные для oauth , можно настроить по своему вкусу (если вы знаете, что делаете). + +После этого используйте команду docker-compose up. Теперь вы должны быть перенаправлены на страницу входа в систему Google OAuth перед доступом к службе. + +#### Шаг 3.4. Добавление Google OAuth для служб Docker + +Возьмем пример панели инструментов Traefik 2. Если вы следовали моему руководству по Traefik, теперь у вас должна быть базовая аутентификация с использованием промежуточного программного обеспечения: + +## Middlewares + +- "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file" + +Или цепочка промежуточного программного обеспечения: + +- "traefik.http.routers.traefik-rtr.middlewares=chain-basic-auth@file" + +Мы уже определили цепочку промежуточного программного обеспечения для Traefik oauth (**chain-oauth**) выше. + +Перейти с базовой аутентификации на oauth теперь так же просто, как изменить **chain-basic-auth** на **chain-oauth** в файле **docker-compose** (показано ниже). + +- "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file" + +Итак, вот и все, вход и аутентификация на основе OAuth для стека обратного прокси-сервера Traefik. + +После этого используйте команду **docker-compose up**. + +#### Шаг 3.5. Добавление OAuth в другие (не Docker) службы + +Приложениями, не относящимися к Docker, могут быть любые службы, находящиеся в хост-системе или в удаленной системе. + +Поставщик файлов Traefik позволяет нам добавлять динамические маршрутизаторы, промежуточное ПО и службы. Раньше мы использовали наш каталог rules только для добавления промежуточного программного обеспечения, но мы можем легко добавить внешний хост, добавив новый файл в этот каталог. Traefik автоматически обнаружит и обновит свои конфигурации. + +Давайте для примера возьмем сервис ex1, работающий на другом хосте (192.168.1.100). + +Чтобы добавить к сервису возможность аутентификации Traefik OAuth2, вам нужно всего лишь создать промежуточное ПО маршрутизатора, как показано ниже. + +http: + +routers: + +ex1-rtr: + +rule: "Host(`ex1.{{env "DOMAINNAME_CLOUD_SERVER"}}`)" + +entryPoints: + +- https + +middlewares: + +- chain-oauth + +service: ex1-svc + +tls: + +certResolver: dns-cloudflare + +services: + +ex1-svc: + +loadBalancer: + +servers: + +- url: "http://192.168.1.100:80" # or whatever your external host's IP:port is + +Интерфейс ex1 будет доступен по адресу **ex1.example.com**, при условии, что для переменной среды **DOMAINNAME_CLOUD_SERVER** установлено значение **example.com** и она передается в контейнер Traefik. + +Поскольку каталог rules является динамическим, просто добавив этот файл в этот каталог, мы создали маршрут. Вы должны иметь возможность подключиться к ex1 через Google OAuth2 без перезапуска Traefik! + +## ОБХОД OAUTH / ВЫБОРОЧНАЯ АУТЕНТИФИКАЦИЯ + +Некоторые приложения не могут аутентифицировать себя и пройти через авторизацию Oauth. Для этого есть обход Oauth на основе правил [Auth Forwarder GitHub](https://github.com/thomseddon/traefik-forward-auth). + +Вы можете обойти аутентификацию на основе определенных ключей в заголовках, регулярных выражениях, хосте, пути, запросе и многом другом. + +**Примечание.** Используя неправильно указанное правило, вы можете легко отключить аутентификацию, когда не собираетесь этого делать. Поэтому я настоятельно рекомендую конкретные и узкие правила обхода аутентификации. + +### Определение правила обхода + +Как мы можем выяснить, какие конкретные правила использовать? + +Это может быть довольно сложно. Как указано в приведенной ниже ссылке, общий способ обхода аутентификации — использование пути. + +Но это может ослабить безопасность, и я рекомендую установить определенные правила. Например, если в заголовке запроса содержится ключ API, аутентификация будет пропущена. + +Проверьте журналы Docker для контейнера OAuth (основные команды Docker). Это выдаст почти все, что происходит в этом контейнере, что может быть ошеломляющим. Вы можете сократить это до интересующего вас приложения, введя команду grep ****. + +### Указание правила обхода OAuth + +Обратите внимание, что **uri** в логах может содержать ключ API (X-Api-Key:[apikey]). Таким образом, вы можете установить использование обхода на основе этого следующим образом. На примере файла middleware сервиса ex1: + +В строчку + +rule: "Host(`ex1.{{env "DOMAINNAME_CLOUD_SERVER"}}`)" + +Дописываем + +rule: "Host(`ex1.{{env "DOMAINNAME_CLOUD_SERVER"}}`) && Headers(`X-Api-Key`, `$API_KEY`)" + +Перезапустите контейнер OAuth и попробуйте сейчас получить доступ к ex1 через приложение и браузер. Браузер должен представить логин OAuth, а приложение должно направить вас напрямую к сервису. + +### Использование пользовательских заголовков + +Некоторые приложения позволяют добавлять собственные заголовки. Поэтому, когда приложение пытается связаться с вашим Radarr, Sonarr и т. д., может быть отправлен собственный заголовок. + +Затем этот настраиваемый заголовок можно отслеживать и, если он присутствует, можно использовать для запуска обхода. Это альтернатива поиску ключей API. Вы можете установить один стандартный заголовок для всех приложений и использовать для всех одно и то же правило обхода. Это также устраняет догадки и пробы и ошибки, описанные выше. + +## OAUTH И ЗАГОЛОВКИ БЕЗОПАСНОСТИ + +Одна вещь, которую следует отметить при использовании службы **Traefik OAuth2**, — это ваши заголовки безопасности. Если служба использует **OAuth** и вы пытаетесь проверить, применяются ли ваши заголовки безопасности, вы, вероятно, получите более низкую оценку. + +## FAQ + +### **Что такое traefik-forward-auth-provider?** + +Прямая аутентификация Traefik — это служба, которая интегрируется со сторонним поставщиком аутентификации (например, Google, Microsoft, Authelia и т. д.) для защиты ваших служб и веб-приложений. + +### **В чем разница между OIDC и OAuth?** + +OIDC или OpenID Connect (OIDC) — это протокол аутентификации. Это набор спецификаций, основанный на OAuth 2.0, который добавляет дополнительные функции. По сути, OIDC — это аутентичный протокол, а OAuth — набор спецификаций для доступа к ресурсам и их совместного использования. + +### Существуют ли другие (более частные) альтернативы Google OAuth? + +Да. [Authelia](https://github.com/authelia/authelia) и [Keycloak](https://github.com/keycloak/keycloak) – два, о которых я могу вспомнить. ИМХО, Authelia была намного проще в настройке, чем Keycloak. Существует также [Authentik](https://goauthentik.io/). \ No newline at end of file diff --git a/docs/images/other/office/excel_vba_01.png b/docs/images/other/office/excel_vba_01.png new file mode 100644 index 0000000..8e868c4 Binary files /dev/null and b/docs/images/other/office/excel_vba_01.png differ diff --git a/docs/other/chrome.md b/docs/other/chrome.md new file mode 100755 index 0000000..79bdb86 --- /dev/null +++ b/docs/other/chrome.md @@ -0,0 +1,19 @@ +Google Chrome + +## Блокировка медиакнопок + +Одним словом, то пока можно только отключить. Но не весь браузер, а только упомянутую функцию поддержки мультимедийных кнопок в нем. Делается это путем отключения соответствующего «*флага*» (экспериментальной функции) в настройках Chrome. Для этого: + +1. открываем браузер в адресную строку копируем `chrome:flags/#hardware-media-key-handling` и жмем Enter +2. далее для функции Hardware Media Key Handling вместо значения «`Default`» устанавливаем «`Disabled` +3. перезапускаем Chrome, чтобы активировать изменение. + + + +
report - click this + +cpu_adam ............... [NO] ....... [OKAY] +cpu_adagrad ............ [NO] ....... [OKAY] +fused_adam ............. [NO] ....... [OKAY] + +
\ No newline at end of file diff --git a/docs/other/office/excel_vba.md b/docs/other/office/excel_vba.md new file mode 100644 index 0000000..b724151 --- /dev/null +++ b/docs/other/office/excel_vba.md @@ -0,0 +1,422 @@ +## Защита страницы через VBA + +Каждый кто хоть раз писал макросы, сталкивался с тем, что требуется защитить лист и формулы на нем от шаловливых ручек пользователей. При том, нужно чтобы макросы на листе работали. Самое просто решение, это перед кодом макроса, добавить это: + +```vba +Worksheets("Лист1").Unprotect Password:="123" +'тут макрос делает действия +Worksheets("Лист1").Protect Password:="123" +``` + +Это будет работать, но у такого подхода есть и свои минусы. Во-первых, нужно эту конструкцию размещать в каждом макросе. Во-вторых - если будет ошибка, лист останется без защиты. + +### Есть другой способ + +Нажмите `Alt+F11`, чтобы попасть в редактор Visual Basic. Затем в левом верхнем углу в окне Project Explorer (если его не видно, то нажмите Ctrl+R) модуль ЭтаКнига (ThisWorkbook) и откройте двойным щелчком: + +![]( ../../images/other/office/excel_vba_01.png){ loading=lazy } + + +Вставьте этот код: + +```vba +Private Sub Workbook_Open() + 'включаем защиту первого листа для пользователя, но не макроса + Worksheets("Лист1").Protect Password:="123", UserInterfaceOnly:=True + + 'второй лист защищаем аналогично, но с возможностью пользоваться группировкой + Worksheets("Лист2").EnableOutlining = True + Worksheets("Лист2").Protect Password:="555", UserInterfaceOnly:=True +End Sub +``` + +Данный код будет автоматически запускаться при открытии файла и ставить защиту на заданные листы. Параметр `UserInterfaceOnly` указывает Excel, что защита не должна работать для действий макроса, а только на операции юзера. +Второй параметр `EnableOutlining` разрешает пользоваться группировкой. + +## Исправление примечаний VBA + +Бывает так, что ты вставляешь примечания и они уползают вниз при действиях со строками.  + +Чтобы такого не было, используй этот макрос: + +```vba +Sub align_comments() +Dim x As Comment +For Each x In ActiveSheet.Comments + x.Shape.Left = x.Parent.Offset(0, 1).Left + 10 + x.Shape.Top = x.Parent.Top +Next +End Sub +``` + +## Открытие файла VBA + +Для открытия 1 файла и передачи его на дальнейшую обработку, используй этот код: + +```vba +avFiles = Application.GetOpenFilename _ + ("Excel files(*.xls*),*.xls*", 1, "Выбери Excel файл", , False) +If VarType(avFiles) = vbBoolean Then + 'была нажата кнопка отмены - выход из процедуры + Exit Sub +End If + +Set avFiles1 = Workbooks.Open(Filename:=avFiles) +``` + +Чтобы открыть много файлов и запустить обработку по ним, используем цикл: + +```vba +FilesToOpen = Application.GetOpenFilename _ + (FileFilter:="All files (*.*), *.*", _ + MultiSelect:=True, Title:="Files to Merge") + +If TypeName(FilesToOpen) = "Boolean" Then + MsgBox "Не выбрано ни одного файла!" + Exit Sub +End If + +'проходим по всем выбранным файлам +x = 1 +While x <= UBound(FilesToOpen) + With Workbooks.Open(FilesToOpen(x)).Sheets(1) + ... + ... + End With + x = x + 1 +Wend +``` + +## Отправка почты VBA + +отправляет почту, используя для этого запущенный MS Outlook + +```vba +' Запрос ввода темы письма + Dim vRetVal + vRetVal = InputBox("Введи тему письма", "Тема", "Test") + ActiveSheet.Range("I3").Value = vRetVal + + Dim OutApp As Object + Dim OutMail As Object + Dim cell As Range + + Send_ist = Cells(1, 1) + + Application.ScreenUpdating = False + Set OutApp = CreateObject("Outlook.Application") + OutApp.Session.Logon + Set OutMail = OutApp.CreateItem(0) + On Error Resume Next + With OutMail + .To = Send_ist + .Body = "Заполнить в день получения и отправить обратно на your_email" + .Subject = Range("A1").Value + .Attachments.Add iFullName + .Send + End With + + On Error GoTo 0 + Set OutMail = Nothing +``` + +## Отключение обновления экрана +```vba +Application.ScreenUpdating = False +' в конце +Application.ScreenUpdating = True +``` + +## Прогресс бар VBA + +> Использование APPLICATION.STATUSBAR +{.is-info} + +### Прогресс бар внизу страницы: +```vba +Application.StatusBar = "TEST" + DoEvents + ... +Application.StatusBar = False +``` + +### Прогресс бар для циклов: +```vba +For i = 1 To n + Istochnik = Cells(i, 20) + Application.StatusBar = "Делаю источник " & i & "-" & Istochnik & "/" & 50 & "" + DoEvents +Next +``` +### Можно сделать показ % завершения: + +![](https://pics.thest1tch.ru/pic/xwbza0bv.png) + +```vba +Sub ShowProgressBar() + Dim lAllCnt As Long, lr as Long + Dim rc As Range + 'кол-во ячеек в выделенной области + lAllCnt = Selection.Count + 'цикл по всем ячейкам в выделенной области + For Each rc In Selection + 'прибавляем 1 при каждом шаге + lr = lr + 1 + Application.StatusBar = "Выполнено: " & Int(100 * lr / lAllCnt) & "%" + DoEvents 'чтобы форма перерисовывалась + Next + 'сбрасываем значение статусной строки + Application.StatusBar = False +End Sub +``` +### Текст + блоки символов из 10 штук: + +![](https://pics.thest1tch.ru/pic/umeq366g.png) + +```vba +Sub StatusBar2() + Dim lr As Long, lp As Double + Dim lAllCnt As Long 'кол-во итераций + Dim s As String + lAllCnt = 10000 + For lr = 1 To lAllCnt + lp = lr \ 100 'десятая часть всего массива + 'формируем строку символов(от 1 до 10) + s = String(lp \ 10, ChrW(10152)) & String(11 - lp \ 10, ChrW(8700)) + Application.StatusBar = "Выполнено: " & lp & "% " & s: DoEvents + DoEvents + Next + 'очищаем статус-бар от значений после выполнения + Application.StatusBar = False +End Sub +``` + +### Текст + блоки квадратов из n штук: + +количество квадратов можно менять +![](https://pics.thest1tch.ru/pic/pq1o9ua4.png) + +```vba +Sub StatusBar3() + Dim lr As Long + Dim lAllCnt As Long 'кол-во итераций + Const lMaxQuad As Long = 20 'сколько квадратов выводить + lAllCnt = 10000 + + For lr = 1 To lAllCnt + Application.StatusBar = "Выполнено: " & Int(100 * lr / lAllCnt) & "%" & String(CLng(lMaxQuad * lr / lAllCnt), ChrW(9632)) & String(lMaxQuad - CLng(lMaxQuad * lr / lAllCnt), ChrW(9633)) + DoEvents + Next + 'очищаем статус-бар от значений после выполнения + Application.StatusBar = False +End Sub +``` + +## Создание файла VBA + +Простое + +```vba +iFullName = ThisWorkbook.Path & "name.xlsx" +``` +С именем из ячейки: + +```vba +iFullName = ThisWorkbook.Path & "\" & Range("A1").Value & ".xlsx" +``` + +## Список уникальных значений VBA + +```vba +PS = Range("A" & Rows.Count).End(xlUp).Row +Range("N6:N" & PS).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("T11"), Unique:=True +Range("T11:T300").Font.ColorIndex = 5 +MsgBox "Создали уникальный список источников" +``` + +## Удаление пароля VBA + +> Пожалуйста, сделайте резервную копию ваших файлов в первую очередь! +{.is-warning} + +### Для 32 битной версии +Откройте файл(ы), которые содержат ваши заблокированные проекты VBA +Создайте новый файл **xlsm** и сохраните этот код в `Module1` + +```vba +code credited to Siwtom (nick name), a Vietnamese developer + +Option Explicit + +Private Const PAGE_EXECUTE_READWRITE = &H40 + +Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _ + (Destination As Long, Source As Long, ByVal Length As Long) + +Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Long, _ + ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long + +Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long + +Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _ + ByVal lpProcName As String) As Long + +Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, _ + ByVal pTemplateName As Long, ByVal hWndParent As Long, _ + ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer + +Dim HookBytes(0 To 5) As Byte +Dim OriginBytes(0 To 5) As Byte +Dim pFunc As Long +Dim Flag As Boolean + +Private Function GetPtr(ByVal Value As Long) As Long + GetPtr = Value +End Function + +Public Sub RecoverBytes() + If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6 +End Sub + +Public Function Hook() As Boolean + Dim TmpBytes(0 To 5) As Byte + Dim p As Long + Dim OriginProtect As Long + + Hook = False + + pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA") + + + If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then + + MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6 + If TmpBytes(0) <> &H68 Then + + MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6 + + p = GetPtr(AddressOf MyDialogBoxParam) + + HookBytes(0) = &H68 + MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4 + HookBytes(5) = &HC3 + + MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6 + Flag = True + Hook = True + End If + End If +End Function + +Private Function MyDialogBoxParam(ByVal hInstance As Long, _ + ByVal pTemplateName As Long, ByVal hWndParent As Long, _ + ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer + If pTemplateName = 4070 Then + MyDialogBoxParam = 1 + Else + RecoverBytes + MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _ + hWndParent, lpDialogFunc, dwInitParam) + Hook + End If +End Function +``` +Вставьте этот код под вышеуказанным кодом в Module1 и запустите его +```vba +Sub unprotected() + If Hook Then + MsgBox "VBA Project is unprotected!", vbInformation, "*****" + End If +End Sub +``` +Возвращайтесь к своим проектам VBA и наслаждайтесь. + +### Для 64 битной версии: +Откройте файл (ы), содержащий ваши заблокированные проекты VBA. + +Создайте новый файл xlsm и сохраните этот код в `Module1` +```vba +Option Explicit + +Private Const PAGE_EXECUTE_READWRITE = &H40 + +Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _ +(Destination As LongPtr, Source As LongPtr, ByVal Length As LongPtr) + +Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (lpAddress As LongPtr, _ +ByVal dwSize As LongPtr, ByVal flNewProtect As LongPtr, lpflOldProtect As LongPtr) As LongPtr + +Private Declare PtrSafe Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As LongPtr + +Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, _ +ByVal lpProcName As String) As LongPtr + +Private Declare PtrSafe Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As LongPtr, _ +ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _ +ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer + +Dim HookBytes(0 To 5) As Byte +Dim OriginBytes(0 To 5) As Byte +Dim pFunc As LongPtr +Dim Flag As Boolean + +Private Function GetPtr(ByVal Value As LongPtr) As LongPtr + GetPtr = Value +End Function + +Public Sub RecoverBytes() + If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6 +End Sub + +Public Function Hook() As Boolean + Dim TmpBytes(0 To 5) As Byte + Dim p As LongPtr + Dim OriginProtect As LongPtr + + Hook = False + + pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA") + + + If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then + + MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6 + If TmpBytes(0) <> &H68 Then + + MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6 + + p = GetPtr(AddressOf MyDialogBoxParam) + + HookBytes(0) = &H68 + MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4 + HookBytes(5) = &HC3 + + MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6 + Flag = True + Hook = True + End If + End If +End Function + +Private Function MyDialogBoxParam(ByVal hInstance As LongPtr, _ +ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _ +ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer + + If pTemplateName = 4070 Then + MyDialogBoxParam = 1 + Else + RecoverBytes + MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _ + hWndParent, lpDialogFunc, dwInitParam) + Hook + End If +End Function +``` +Вставьте этот код в Module2 и запустите его +```vba +Sub unprotected() + If Hook Then + MsgBox "VBA Project is unprotected!", vbInformation, "*****" + End If +End Sub +``` \ No newline at end of file diff --git a/docs/proxmox/ct-template.md b/docs/proxmox/ct-template.md new file mode 100755 index 0000000..4943b01 --- /dev/null +++ b/docs/proxmox/ct-template.md @@ -0,0 +1,7 @@ +Чтобы создать собственный шаблон контейнера в Proxmox, используйте: + +1. Сделайте резервную копию контейнера в формате gzip. В идеале, когда контейнер остановлен +2. SSH к базовой машине proxmox и переместите резервную копию контейнера в папку шаблона, используя: +3. Теперь можно использовать этот шаблон для создания новых контейнеров. + +`mv /var/lib/vz/dump/<имя-резервной копии>.tar.gz /var/lib/vz/template/cache/<имя-шаблона>.tar.gz` \ No newline at end of file diff --git a/docs/ubuntu/mariadb.md b/docs/ubuntu/mariadb.md old mode 100644 new mode 100755 diff --git a/mkdocs.yml b/mkdocs.yml index 245b74c..611f4f7 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -16,11 +16,15 @@ nav: - Plex Meta Manager: docker-compose/plex-mm.md - Traefik: - Traefik Forward Auth: docker-compose/traefik-forward-auth.md - - :Ubuntu: Ubuntu 22: + - Ubuntu 22: - MariaDB: ubuntu/mariadb.md + - Proxmox: + - CT Template: proxmox/ct-template.md - Помойка: - SSL для сайта: other/ssl-for-site.md - Ubuntu bash aliases: other/ubuntu-bash-aliases.md + - Блог: + - blog/index.md theme: name: material @@ -85,6 +89,8 @@ plugins: lang: - ru - en + - glightbox + - blog markdown_extensions: - abbr diff --git a/requirements.txt b/requirements.txt index b831bb6..c383e08 100755 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,5 @@ mkdocs-material mkdocs-material-extensions>=1.1 mkdocs-minify-plugin>=0.2 mkdocs-git-revision-date-plugin==0.3.1 -pymdown-extensions>=9.9.1 \ No newline at end of file +pymdown-extensions>=9.9.1 +mkdocs-glightbox \ No newline at end of file