Skip to content

Commit

Permalink
Added CLI mode
Browse files Browse the repository at this point in the history
Added additional startup keys
Added group check
Added exception handling if connection and data queue parameters are not set
Moved distonary file to ./.storage directory
Changed variable with `host` on `server` in file secrets.yaml
Code refactoring
Update README.md
  • Loading branch information
Losenmann committed Sep 7, 2024
1 parent 24f8fb0 commit 4f02f78
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 29 deletions.
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@
Python script for Home Assistant adding authentication via RADIUS\
The project is based on the library [pyrad](https://github.com/pyradius/pyrad.git)

## Overview
The script is designed to authenticate users in Home Assistant via a RADIUS server. This allows you to centrally manage user access.<br>
The script supports 2 launch modes: [auth_providers](#usage-in-auth_provider-mode) and [CLI](#usage-in-cli-mode).
For correct operation, you must add to the [dictionary](./dictionary) in the RADIUS server dictionary file.

## Install
[![](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=losenmann&repository=auth-radius&category=python_script)

- **Method 1.** [HACS](https://hacs.xyz) > Python Script > Add > Auth Radius > Install

- **Method 2.** Copy the manually `auth-radius.py` from [latest release](https://github.com/Losenmann/auth-radius/releases/latest) to path `/config/python_scripts`

## Setupe
## Usage in auth_provider mode
### Setupe
- **Home Assistant**
1. Set connection parameters in the `secrets.yaml` file
```yaml
radius_host: "dns_or_ip_addreess_radius_server"
radius_server: "dns_or_ip_addreess_radius_server"
radius_secret: "radius_server_secret"
```
2. In the `configuration.yaml` file add the configuration, the authentication order matters
Expand All @@ -28,11 +34,12 @@ The project is based on the library [pyrad](https://github.com/pyradius/pyrad.gi
auth_providers:
- type: command_line
command: '/usr/local/bin/python'
args: ['/config/python_scripts/auth-radius.py', '--meta']
args: ['/config/python_scripts/auth-radius.py', '-m']
meta: true
- type: homeassistant
```
You can remove the `meta:true` directive so that the script does not write some variables to standard output to populate the user account created in Home Assistant with additional data
> [!NOTE]
> You can remove the `meta: true` directive so that the script does not write some variables to standard output to populate the user account created in Home Assistant with additional data

- **RADIUS**
1. Add data from the file [dictionary](./dictionary) to the RADIUS server's `dictionary` file
Expand All @@ -43,3 +50,22 @@ The project is based on the library [pyrad](https://github.com/pyradius/pyrad.gi
| `Hass-Group` | string | system-users <br> system-admin | User group |
| `Hass-Local-Only` | byte | 0 <br> 1 | Local login only <br> (Defaults to 0) |
| `Hass-Is-Active` | byte | 0 <br> 1 | Activate user account <br> (Defaults to 1) |

## Usage in CLI mode
In CLI mode, you need to set execution permissions `chmod +x ./python_scripts/auth-ldap.py`<br>
Or run via Python `python ./python_scripts/auth-radius.py`
> [!NOTE]
> RADIUS connection parameters can be configured in `secrets.yaml`, see point 1 of the chapter [Usage in auth_provider mode](#usage-in-auth_provider-mode)
```
./python_scripts/auth-radius.py -U 'username' -P 'password' -s 'radius.example.com' -S 'secret'
```
## Script arguments
| key | type | description |
| :--- | :--: | :---------- |
| `-h` | boolean | Get help information |
| `-m` | boolean | Enable meta to output credentials to stdout <br> (Defaults to False) |
| `-U` | string | Username |
| `-P` | string | Password |
| `-s` | string | RADIUS server <br> (Defaults from `secrets.yaml`) |
| `-S` | string | RADIUS secret <br> (Defaults from `secrets.yaml`) |
34 changes: 30 additions & 4 deletions info.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@
Python script for Home Assistant adding authentication via RADIUS\
The project is based on the library [pyrad](https://github.com/pyradius/pyrad.git)

## Overview
The script is designed to authenticate users in Home Assistant via a RADIUS server. This allows you to centrally manage user access.<br>
The script supports 2 launch modes: [auth_providers](#usage-in-auth_provider-mode) and [CLI](#usage-in-cli-mode).
For correct operation, you must add to the [dictionary](./dictionary) in the RADIUS server dictionary file.

## Install
[![](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=losenmann&repository=auth-radius&category=python_script)

- **Method 1.** [HACS](https://hacs.xyz) > Python Script > Add > Auth Radius > Install

- **Method 2.** Copy the manually `auth-radius.py` from [latest release](https://github.com/Losenmann/auth-radius/releases/latest) to path `/config/python_scripts`

## Setupe
## Usage in auth_provider mode
### Setupe
- **Home Assistant**
1. Set connection parameters in the `secrets.yaml` file
```yaml
radius_host: "dns_or_ip_addreess_radius_server"
radius_server: "dns_or_ip_addreess_radius_server"
radius_secret: "radius_server_secret"
```
2. In the `configuration.yaml` file add the configuration, the authentication order matters
Expand All @@ -28,11 +34,12 @@ The project is based on the library [pyrad](https://github.com/pyradius/pyrad.gi
auth_providers:
- type: command_line
command: '/usr/local/bin/python'
args: ['/config/python_scripts/auth-radius.py', '--meta']
args: ['/config/python_scripts/auth-radius.py', '-m']
meta: true
- type: homeassistant
```
You can remove the `meta:true` directive so that the script does not write some variables to standard output to populate the user account created in Home Assistant with additional data
> [!NOTE]
> You can remove the `meta: true` directive so that the script does not write some variables to standard output to populate the user account created in Home Assistant with additional data

- **RADIUS**
1. Add data from the file [dictionary](./dictionary) to the RADIUS server's `dictionary` file
Expand All @@ -43,3 +50,22 @@ The project is based on the library [pyrad](https://github.com/pyradius/pyrad.gi
| `Hass-Group` | string | system-users <br> system-admin | User group |
| `Hass-Local-Only` | byte | 0 <br> 1 | Local login only <br> (Defaults to 0) |
| `Hass-Is-Active` | byte | 0 <br> 1 | Activate user account <br> (Defaults to 1) |

## Usage in CLI mode
In CLI mode, you need to set execution permissions `chmod +x ./python_scripts/auth-ldap.py`<br>
Or run via Python `python ./python_scripts/auth-radius.py`
> [!NOTE]
> RADIUS connection parameters can be configured in `secrets.yaml`, see point 1 of the chapter [Usage in auth_provider mode](#usage-in-auth_provider-mode)
```
./python_scripts/auth-radius.py -U 'username' -P 'password' -s 'radius.example.com' -S 'secret'
```
## Script arguments
| key | type | description |
| :--- | :--: | :---------- |
| `-h` | boolean | Get help information |
| `-m` | boolean | Enable meta to output credentials to stdout <br> (Defaults to False) |
| `-U` | string | Username |
| `-P` | string | Password |
| `-s` | string | RADIUS server <br> (Defaults from `secrets.yaml`) |
| `-S` | string | RADIUS secret <br> (Defaults from `secrets.yaml`) |
74 changes: 53 additions & 21 deletions python_scripts/auth-radius.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,57 @@

def main():
vendor = 812300
parser = argparse.ArgumentParser(description="Home Assistant RADIUS authentication via CLI")
parser.add_argument('-m', '--meta', action='store_true', help='Enable meta to output credentials to stdout')
parser = argparse.ArgumentParser(
prog='Auth RADIUS',
description='Home Assistant RADIUS authentication via CLI',
epilog='https://github.com/Losenmann/auth-radius'
)
parser.add_argument('-m', '--meta', action='store_true', help='enable meta to output credentials to stdout')
parser.add_argument('-U', '--username', type=str, help='username')
parser.add_argument('-P', '--password', type=str, help='user password')
parser.add_argument('-s', '--server', type=str, help='RADIUS server')
parser.add_argument('-S', '--secret', type=str, help='RADIUS secret')
args = parser.parse_args()

if not os.path.isfile("/config/python_scripts/dictionary"):
if not os.path.isfile("/config/.storage/dictionary.radius"):
if not args.meta:
print("Create dictionary file")
f = open("/config/python_scripts/dictionary", "w")
f = open("/config/.storage/dictionary.radius", "w")
f.write(base64.b64decode(DictFileBase64()).decode("utf-8"))
f.close()

with open("/config/secrets.yaml") as fh:
secret = yaml.load(fh, Loader=yaml.FullLoader)
secret = yaml.load(fh, Loader=yaml.FullLoader)
try:
v_username = args.username if args.username else os.environ['username']
except:
print("\033[33m{}\033[0m".format("Username not specified"))
sys.exit(1)
try:
v_password = args.password if args.password else os.environ['password']
except:
print("\033[33m{}\033[0m".format("User password not specified"))
sys.exit(1)
try:
v_server = args.server if args.server else secret['radius_server']
except:
print("\033[33m{}\033[0m".format("Server not specified"))
sys.exit(1)
try:
v_secret = args.secret if args.secret else secret['radius_secret']
except:
print("\033[33m{}\033[0m".format("Server secret not specified"))
sys.exit(1)

srv = Client(
server=bytes(secret["radius_host"], encoding="utf-8"),
secret=bytes(secret["radius_secret"], encoding="utf-8"),
dict=Dictionary("/config/python_scripts/dictionary")
server=bytes(v_server, encoding="utf-8"),
secret=bytes(v_secret, encoding="utf-8"),
dict=Dictionary("/config/.storage/dictionary.radius")
)

req = srv.CreateAuthPacket(code=AccessRequest)
req["User-Name"] = os.environ['username']
req["User-Password"] = req.PwCrypt(os.environ['password'])
req["User-Name"] = v_username
req["User-Password"] = req.PwCrypt(v_password)

try:
if not args.meta:
Expand All @@ -76,20 +104,24 @@ def main():
sys.exit(1)

if reply.code == AccessAccept:
v_local_only = "false"
if int(reply[(vendor, 2)][0].hex(), 16) > 0:
v_local_only = "true"
if args.meta:
print("name=" + req["User-Name"][0])
print("group=" + reply[(vendor, 1)][0].decode("utf-8"))
print("local_only=" + v_local_only)
print("is_activ=" + "true")
if reply[(vendor, 1)][0].decode("utf-8") in ['system-admin', 'system-users']:
v_local_only = "false"
if int(reply[(vendor, 2)][0].hex(), 16) > 0:
v_local_only = "true"
if args.meta:
print("name=" + req["User-Name"][0])
print("group=" + reply[(vendor, 1)][0].decode("utf-8"))
print("local_only=" + v_local_only)
print("is_activ=" + "true")
else:
print("\033[32m{}\033[0m".format("Access accepted"))
exit(0)
else:
print("Access accepted")
exit(0)
if not args.meta:
print("\033[31m{}\033[0m".format("Insufficient access rights"))
else:
if not args.meta:
print("Access denied")
print("\033[31m{}\033[0m".format("Access denied"))
exit(1)

"""bidict.py"""
Expand Down

0 comments on commit 4f02f78

Please sign in to comment.