add new
continuous-integration/drone/push Build is passing Details

pull/6/head
thest1tch 2 years ago
parent 99cc2c60b1
commit c6d1b51a8a

@ -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
path: /opt/appdata/mkdocswiki
- name: site-st1tru
host:
path: /opt/appdata/nginx/st1t.ru

@ -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/).

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

@ -0,0 +1,19 @@
Google Chrome
## Блокировка медиакнопок
Одним словом, то пока можно только отключить. Но не весь браузер, а только упомянутую функцию поддержки мультимедийных кнопок в нем. Делается это путем отключения соответствующего «*флага*» (экспериментальной функции) в настройках Chrome. Для этого:
1. открываем браузер в адресную строку копируем `chrome:flags/#hardware-media-key-handling` и жмем Enter
2. далее для функции Hardware Media Key Handling вместо значения «`Default`» устанавливаем «`Disabled`
3. перезапускаем Chrome, чтобы активировать изменение.
<details><summary>report - click this</summary>
<code>
cpu_adam ............... [NO] ....... [OKAY]
cpu_adagrad ............ [NO] ....... [OKAY]
fused_adam ............. [NO] ....... [OKAY]
</code>
</details>

@ -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
```

@ -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`

@ -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

@ -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
pymdown-extensions>=9.9.1
mkdocs-glightbox
Loading…
Cancel
Save