From cbe95faf317344c84a66bd615421fae5f87d9907 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Thu, 27 Jan 2022 16:39:19 +0300 Subject: [PATCH] first commit --- .gitignore | 2 + book.toml | 6 + src/SUMMARY.md | 8 + src/rest-api/api.md | 1254 +++++++++++++++++++++++++++++++ src/rest-api/auth.md | 1 + src/rest-api/changelog.md | 70 ++ src/rest-api/migrations.md | 66 ++ src/rest-api/testing.md | 9 + src/rest-api/vulnerabilities.md | 22 + 9 files changed, 1438 insertions(+) create mode 100644 .gitignore create mode 100644 book.toml create mode 100644 src/SUMMARY.md create mode 100644 src/rest-api/api.md create mode 100644 src/rest-api/auth.md create mode 100644 src/rest-api/changelog.md create mode 100644 src/rest-api/migrations.md create mode 100644 src/rest-api/testing.md create mode 100644 src/rest-api/vulnerabilities.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62d2979 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +book +.obsidian diff --git a/book.toml b/book.toml new file mode 100644 index 0000000..06a74a3 --- /dev/null +++ b/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["Inex Code"] +language = "en" +multilingual = false +src = "src" +title = "SelfPrivacy developer docs" diff --git a/src/SUMMARY.md b/src/SUMMARY.md new file mode 100644 index 0000000..c779f12 --- /dev/null +++ b/src/SUMMARY.md @@ -0,0 +1,8 @@ +# SelfPrivacy REST API + +- [API Reference](rest-api/api.md) +- [Authorization](rest-api/auth.md) +- [Changelog](rest-api/changelog.md) +- [Migrations](rest-api/migrations.md) +- [Testing, linting](rest-api/testing.md) +- [Vulnerabilities](rest-api/vulnerabilities.md) diff --git a/src/rest-api/api.md b/src/rest-api/api.md new file mode 100644 index 0000000..f3d2a51 --- /dev/null +++ b/src/rest-api/api.md @@ -0,0 +1,1254 @@ +# SelfPrivacy API +API available as Swagger documentation, markdown version is below. + +### Version + +1.2.0 + +## Content negotiation + +**URI Scheme**: http + +**Consumes**: application/json + +**Produces**: application/json + +## Access control + * bearerAuth + +## All endpoints + +### backups + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| GET | /services/restic/backup/list | [get services restic backup list](#get-services-restic-backup-list) | Get all restic backups | +| GET | /services/restic/backup/reload | [get services restic backup reload](#get-services-restic-backup-reload) | Force reload snapshots | +| GET | /services/restic/backup/status | [get services restic backup status](#get-services-restic-backup-status) | Get backup status | +| PUT | /services/restic/backblaze/config | [put services restic backblaze config](#put-services-restic-backblaze-config) | Set the new key for backblaze | +| PUT | /services/restic/backup/create | [put services restic backup create](#put-services-restic-backup-create) | Initiate a new restic backup | +| PUT | /services/restic/backup/restore | [put services restic backup restore](#put-services-restic-backup-restore) | Start backup restoration | + + + +### bitwarden + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| POST | /services/bitwarden/disable | [post services bitwarden disable](#post-services-bitwarden-disable) | Disable Bitwarden | +| POST | /services/bitwarden/enable | [post services bitwarden enable](#post-services-bitwarden-enable) | Enable Bitwarden | + + + +### email + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| GET | /services/mailserver/dkim | [get services mailserver dkim](#get-services-mailserver-dkim) | Get DKIM key from file | + + + +### gitea + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| POST | /services/gitea/disable | [post services gitea disable](#post-services-gitea-disable) | Disable Gitea | +| POST | /services/gitea/enable | [post services gitea enable](#post-services-gitea-enable) | Enable Gitea | + + + +### nextcloud + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| POST | /services/nextcloud/disable | [post services nextcloud disable](#post-services-nextcloud-disable) | Disable Nextcloud | +| POST | /services/nextcloud/enable | [post services nextcloud enable](#post-services-nextcloud-enable) | Enable Nextcloud | + + + +### o_cserv + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| POST | /services/ocserv/disable | [post services ocserv disable](#post-services-ocserv-disable) | Disable OCserv | +| POST | /services/ocserv/enable | [post services ocserv enable](#post-services-ocserv-enable) | Enable OCserv | + + + +### pleroma + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| POST | /services/pleroma/disable | [post services pleroma disable](#post-services-pleroma-disable) | Disable Pleroma | +| POST | /services/pleroma/enable | [post services pleroma enable](#post-services-pleroma-enable) | Enable Pleroma | + + + +### services + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| GET | /services/status | [get services status](#get-services-status) | Get service status | + + + +### ssh + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| DELETE | /services/ssh/keys/{username} | [delete services SSH keys username](#delete-services-ssh-keys-username) | Delete SSH key | +| GET | /services/ssh | [get services SSH](#get-services-ssh) | Get current SSH settings | +| GET | /services/ssh/keys/{username} | [get services SSH keys username](#get-services-ssh-keys-username) | List SSH keys | +| POST | /services/ssh/enable | [post services SSH enable](#post-services-ssh-enable) | Enable SSH | +| POST | /services/ssh/keys/{username} | [post services SSH keys username](#post-services-ssh-keys-username) | Add SSH key to the user | +| PUT | /services/ssh | [put services SSH](#put-services-ssh) | Change SSH settings | +| PUT | /services/ssh/key/send | [put services SSH key send](#put-services-ssh-key-send) | Add a SSH root key | + + + +### system + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| GET | /api/version | [get API version](#get-api-version) | Get API version | +| GET | /system/configuration/apply | [get system configuration apply](#get-system-configuration-apply) | Rebuild NixOS with nixos-rebuild switch | +| GET | /system/configuration/autoUpgrade | [get system configuration auto upgrade](#get-system-configuration-auto-upgrade) | Get current system autoupgrade settings | +| GET | /system/configuration/pull | [get system configuration pull](#get-system-configuration-pull) | Pull Repository Changes | +| GET | /system/configuration/rollback | [get system configuration rollback](#get-system-configuration-rollback) | Rollback NixOS with nixos-rebuild switch --rollback | +| GET | /system/configuration/timezone | [get system configuration timezone](#get-system-configuration-timezone) | Get current system timezone | +| GET | /system/configuration/upgrade | [get system configuration upgrade](#get-system-configuration-upgrade) | Upgrade NixOS with nixos-rebuild switch --upgrade | +| GET | /system/pythonVersion | [get system python version](#get-system-python-version) | Get python version used by this API | +| GET | /system/reboot | [get system reboot](#get-system-reboot) | Reboot the system | +| GET | /system/version | [get system version](#get-system-version) | Get system version from uname -a | +| PUT | /system/configuration/autoUpgrade | [put system configuration auto upgrade](#put-system-configuration-auto-upgrade) | Change system auto upgrade settings | +| PUT | /system/configuration/timezone | [put system configuration timezone](#put-system-configuration-timezone) | Change system timezone | + + + +### tokens + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| DELETE | /auth/tokens | [delete auth tokens](#delete-auth-tokens) | Delete token | +| GET | /auth/recovery_token | [get auth recovery token](#get-auth-recovery-token) | Get recovery token status | +| GET | /auth/tokens | [get auth tokens](#get-auth-tokens) | Get current device tokens | +| POST | /auth/new_device | [post auth new device](#post-auth-new-device) | Get new device token | +| POST | /auth/new_device/authorize | [post auth new device authorize](#post-auth-new-device-authorize) | Authorize device | +| POST | /auth/recovery_token | [post auth recovery token](#post-auth-recovery-token) | Generate recovery token | +| POST | /auth/recovery_token/use | [post auth recovery token use](#post-auth-recovery-token-use) | Use recovery token | +| POST | /auth/tokens | [post auth tokens](#post-auth-tokens) | Refresh token | + + + +### users + +| Method | URI | Name | Summary | +|---------|---------|--------|---------| +| DELETE | /users/{username} | [delete users username](#delete-users-username) | Delete a user | +| GET | /users | [get users](#get-users) | Get a list of users | +| POST | /users | [post users](#post-users) | Create a new user | + + + +## Paths + +### Delete token (*DeleteAuthTokens*) + +``` +DELETE /auth/tokens +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| token | `body` | [DeleteAuthTokensBody](#delete-auth-tokens-body) | `DeleteAuthTokensBody` | | ✓ | | Token's name to delete | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#delete-auth-tokens-200) | OK | Token deleted | +| [400](#delete-auth-tokens-400) | Bad Request | Bad request | +| [404](#delete-auth-tokens-404) | Not Found | Token not found | + +###### Inlined models + +** DeleteAuthTokensBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| token | string| `string` | ✓ | | Token name to delete | | + + + +### Delete SSH key (*DeleteServicesSSHKeysUsername*) + +``` +DELETE /services/ssh/keys/{username} +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| username | `path` | string | `string` | | ✓ | | User to delete keys for | +| public_key | `body` | [DeleteServicesSSHKeysUsernameBody](#delete-services-ssh-keys-username-body) | `DeleteServicesSSHKeysUsernameBody` | | ✓ | | Key to delete | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#delete-services-ssh-keys-username-200) | OK | SSH key deleted | +| [401](#delete-services-ssh-keys-username-401) | Unauthorized | Unauthorized | +| [404](#delete-services-ssh-keys-username-404) | Not Found | Key not found | + +###### Inlined models + +** DeleteServicesSSHKeysUsernameBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| public_key | string| `string` | ✓ | | | | + + + +### Delete a user (*DeleteUsersUsername*) + +``` +DELETE /users/{username} +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| username | `path` | string | `string` | | ✓ | | User to delete | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#delete-users-username-200) | OK | Deleted user | +| [400](#delete-users-username-400) | Bad Request | Bad request | +| [401](#delete-users-username-401) | Unauthorized | Unauthorized | +| [404](#delete-users-username-404) | Not Found | User not found | + +### Get API version (*GetAPIVersion*) + +``` +GET /api/version +``` + +#### All responses +| Code | Status | Description | Schema | +|------|--------|-------------|--------| +| [200](#get-api-version-200) | OK | API version | [schema](#get-api-version-200-schema) | +| [401](#get-api-version-401) | Unauthorized | Unauthorized | + +#### Responses +##### 200 - API version +Status: OK + +###### Schema +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| version | string| `string` | | | API version | | + +##### 401 - Unauthorized +Status: Unauthorized + +### Get recovery token status (*GetAuthRecoveryToken*) + +``` +GET /auth/recovery_token +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | Has headers | Schema | +|------|--------|-------------|:-----------:|--------| +| [200](#get-auth-recovery-token-200) | OK | Recovery token status | | [schema](#get-auth-recovery-token-200-schema) | +| [400](#get-auth-recovery-token-400) | Bad Request | Bad request | | [schema](#get-auth-recovery-token-400-schema) | + +#### Responses + +##### 200 - Recovery token status +Status: OK + +###### Schema +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| date | string| `string` | | | Recovery token date | | +| exists | boolean| `bool` | | | Recovery token exists | | +| expiration | string| `string` | | | Recovery token expiration date | | +| uses_left | integer| `int64` | | | Recovery token uses left | | +| valid | boolean| `bool` | | | Recovery token is valid | | + +##### 400 - Bad request +Status: Bad Request + +### Get current device tokens (*GetAuthTokens*) + +``` +GET /auth/tokens +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-auth-tokens-200) | OK | List of tokens | +| [400](#get-auth-tokens-400) | Bad Request | Bad request | + + +### Get DKIM key from file (*GetServicesMailserverDkim*) + +``` +GET /services/mailserver/dkim +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-services-mailserver-dkim-200) | OK | DKIM key encoded in base64 | +| [401](#get-services-mailserver-dkim-401) | Unauthorized | Unauthorized | +| [404](#get-services-mailserver-dkim-404) | Not Found | DKIM key not found | + + +### Get all restic backups (*GetServicesResticBackupList*) + +``` +GET /services/restic/backup/list +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-services-restic-backup-list-200) | OK | A list of snapshots | +| [400](#get-services-restic-backup-list-400) | Bad Request | Bad request | +| [401](#get-services-restic-backup-list-401) | Unauthorized | Unauthorized | + + +### Force reload snapshots (*GetServicesResticBackupReload*) + +``` +GET /services/restic/backup/reload +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-services-restic-backup-reload-200) | OK | Snapshots reloaded | +| [400](#get-services-restic-backup-reload-400) | Bad Request | Bad request | +| [401](#get-services-restic-backup-reload-401) | Unauthorized | Unauthorized | + + +### Get backup status (*GetServicesResticBackupStatus*) + +``` +GET /services/restic/backup/status +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-services-restic-backup-status-200) | OK | Backup status | +| [400](#get-services-restic-backup-status-400) | Bad Request | Bad request | +| [401](#get-services-restic-backup-status-401) | Unauthorized | Unauthorized | + + + +### Get current SSH settings (*GetServicesSSH*) + +``` +GET /services/ssh +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-services-ssh-200) | OK | SSH settings | +| [400](#get-services-ssh-400) | Bad Request | Bad request | + +### List SSH keys (*GetServicesSSHKeysUsername*) + +``` +GET /services/ssh/keys/{username} +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| username | `path` | string | `string` | | ✓ | | User to list keys for | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-services-ssh-keys-username-200) | OK | SSH keys | +| [401](#get-services-ssh-keys-username-401) | Unauthorized | Unauthorized | + + +### Get service status (*GetServicesStatus*) + +``` +GET /services/status +``` + +#### All responses +| Code | Status | Description | Schema | +|------|--------|-------------|--------| +| [200](#get-services-status-200) | OK | Service status | [schema](#get-services-status-200-schema) | +| [401](#get-services-status-401) | Unauthorized | Unauthorized | [schema](#get-services-status-401-schema) | + +#### Responses + + +##### 200 - Service status +Status: OK + +###### Schema + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| bitwarden | integer| `int64` | | | Bitwarden service status | | +| gitea | integer| `int64` | | | Gitea service status | | +| http | integer| `int64` | | | Nginx service status | | +| imap | integer| `int64` | | | Dovecot service status | | +| nextcloud | integer| `int64` | | | Nextcloud service status | | +| ocserv | integer| `int64` | | | OpenConnect VPN service status | | +| pleroma | integer| `int64` | | | Pleroma service status | | +| smtp | integer| `int64` | | | Postfix service status | | + +##### 401 - Unauthorized +Status: Unauthorized + + + +### Rebuild NixOS with nixos-rebuild switch (*GetSystemConfigurationApply*) + +``` +GET /system/configuration/apply +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-configuration-apply-200) | OK | System rebuild has started | +| [401](#get-system-configuration-apply-401) | Unauthorized | Unauthorized | + + +### Get current system autoupgrade settings (*GetSystemConfigurationAutoUpgrade*) + +``` +GET /system/configuration/autoUpgrade +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-configuration-auto-upgrade-200) | OK | Auto-upgrade settings | +| [400](#get-system-configuration-auto-upgrade-400) | Bad Request | Bad request | + + +### Pull Repository Changes (*GetSystemConfigurationPull*) + +``` +GET /system/configuration/pull +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-configuration-pull-200) | OK | Got update | +| [201](#get-system-configuration-pull-201) | Created | Nothing to update | +| [401](#get-system-configuration-pull-401) | Unauthorized | Unauthorized | +| [500](#get-system-configuration-pull-500) | Internal Server Error | Something went wrong | + + +### Rollback NixOS with nixos-rebuild switch --rollback (*GetSystemConfigurationRollback*) + +``` +GET /system/configuration/rollback +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-configuration-rollback-200) | OK | System rollback has started | +| [401](#get-system-configuration-rollback-401) | Unauthorized | Unauthorized | + +### Get current system timezone (*GetSystemConfigurationTimezone*) + +``` +GET /system/configuration/timezone +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-configuration-timezone-200) | OK | Timezone | +| [400](#get-system-configuration-timezone-400) | Bad Request | Bad request | + +### Upgrade NixOS with nixos-rebuild switch --upgrade (*GetSystemConfigurationUpgrade*) + +``` +GET /system/configuration/upgrade +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-configuration-upgrade-200) | OK | System upgrade has started | +| [401](#get-system-configuration-upgrade-401) | Unauthorized | Unauthorized | + +### Get python version used by this API (*GetSystemPythonVersion*) + +``` +GET /system/pythonVersion +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-python-version-200) | OK | OK | +| [401](#get-system-python-version-401) | Unauthorized | Unauthorized | + + +### Reboot the system (*GetSystemReboot*) + +``` +GET /system/reboot +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-reboot-200) | OK | System reboot has started | +| [401](#get-system-reboot-401) | Unauthorized | Unauthorized | + +### Get system version from uname -a (*GetSystemVersion*) + +``` +GET /system/version +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-system-version-200) | OK | OK | +| [401](#get-system-version-401) | Unauthorized | Unauthorized | + + + +### Get a list of users (*GetUsers*) + +``` +GET /users +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#get-users-200) | OK | A list of users | +| [401](#get-users-401) | Unauthorized | Unauthorized | + +### Get new device token (*PostAuthNewDevice*) + +``` +POST /auth/new_device +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-auth-new-device-200) | OK | New device token | +| [400](#post-auth-new-device-400) | Bad Request | Bad request | + + +### Authorize device (*PostAuthNewDeviceAuthorize*) + +``` +POST /auth/new_device/authorize +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| data | `body` | [PostAuthNewDeviceAuthorizeBody](#post-auth-new-device-authorize-body) | `PostAuthNewDeviceAuthorizeBody` | | ✓ | | Who is authorizing | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-auth-new-device-authorize-200) | OK | Device authorized | +| [400](#post-auth-new-device-authorize-400) | Bad Request | Bad request | +| [404](#post-auth-new-device-authorize-404) | Not Found | Token not found | + +###### Inlined models + +** PostAuthNewDeviceAuthorizeBody** + + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| device | string| `string` | | | Device to authorize | | +| token | string| `string` | | | Mnemonic token to authorize | | + + + +### Generate recovery token (*PostAuthRecoveryToken*) + +``` +POST /auth/recovery_token +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| data | `body` | [PostAuthRecoveryTokenBody](#post-auth-recovery-token-body) | `PostAuthRecoveryTokenBody` | | ✓ | | Token data | + +#### All responses +| Code | Status | Description | Schema | +|------|--------|-------------|--------| +| [200](#post-auth-recovery-token-200) | OK | Recovery token generated| [schema](#post-auth-recovery-token-200-schema) | +| [400](#post-auth-recovery-token-400) | Bad Request | Bad request || + +#### Responses + + +##### 200 - Recovery token generated +Status: OK + +###### Schema +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| token | string| `string` | | | Mnemonic recovery token | | + +##### 400 - Bad request +Status: Bad Request + +###### Inlined models + +** PostAuthRecoveryTokenBody** + + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| expiration | string| `string` | | | Token expiration date | | +| uses | integer| `int64` | | | Token uses | | + + +### Use recovery token (*PostAuthRecoveryTokenUse*) + +``` +POST /auth/recovery_token/use +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| data | `body` | [PostAuthRecoveryTokenUseBody](#post-auth-recovery-token-use-body) | `PostAuthRecoveryTokenUseBody` | | ✓ | | Token data | + +#### All responses +| Code | Status | Description | Schema | +|------|--------|-------------|--------| +| [200](#post-auth-recovery-token-use-200) | OK | Recovery token used | [schema](#post-auth-recovery-token-use-200-schema) | +| [400](#post-auth-recovery-token-use-400) | Bad Request | Bad request | +| [404](#post-auth-recovery-token-use-404) | Not Found | Token not found | + +#### Responses + + +##### 200 - Recovery token used +Status: OK + +###### Schema +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| token | string| `string` | | | Device authorization token | | + + + +###### Inlined models + +** PostAuthRecoveryTokenUseBody** + + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| device | string| `string` | | | Device to authorize | | +| token | string| `string` | | | Mnemonic recovery token | | + + + + +### Refresh token (*PostAuthTokens*) + +``` +POST /auth/tokens +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-auth-tokens-200) | OK | Token refreshed | +| [400](#post-auth-tokens-400) | Bad Request | Bad request | +| [404](#post-auth-tokens-404) | Not Found | Token not found | + +### Disable Bitwarden (*PostServicesBitwardenDisable*) + +``` +POST /services/bitwarden/disable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-bitwarden-disable-200) | OK | Bitwarden disabled | +| [401](#post-services-bitwarden-disable-401) | Unauthorized | Unauthorized | + + +### Enable Bitwarden (*PostServicesBitwardenEnable*) + +``` +POST /services/bitwarden/enable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-bitwarden-enable-200) | OK | Bitwarden enabled | +| [401](#post-services-bitwarden-enable-401) | Unauthorized | Unauthorized | + + +### Disable Gitea (*PostServicesGiteaDisable*) + +``` +POST /services/gitea/disable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-gitea-disable-200) | OK | Gitea disabled | +| [401](#post-services-gitea-disable-401) | Unauthorized | Unauthorized | + + +### Enable Gitea (*PostServicesGiteaEnable*) + +``` +POST /services/gitea/enable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-gitea-enable-200) | OK | Gitea enabled | +| [401](#post-services-gitea-enable-401) | Unauthorized | Unauthorized | + +### Disable Nextcloud (*PostServicesNextcloudDisable*) + +``` +POST /services/nextcloud/disable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-nextcloud-disable-200) | OK | Nextcloud disabled | +| [401](#post-services-nextcloud-disable-401) | Unauthorized | Unauthorized | + +### Enable Nextcloud (*PostServicesNextcloudEnable*) + +``` +POST /services/nextcloud/enable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-nextcloud-enable-200) | OK | Nextcloud enabled | +| [401](#post-services-nextcloud-enable-401) | Unauthorized | Unauthorized | + + +### Disable OCserv (*PostServicesOcservDisable*) + +``` +POST /services/ocserv/disable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-ocserv-disable-200) | OK | OCserv disabled | +| [401](#post-services-ocserv-disable-401) | Unauthorized | Unauthorized | + + +### Enable OCserv (*PostServicesOcservEnable*) + +``` +POST /services/ocserv/enable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-ocserv-enable-200) | OK | OCserv enabled | +| [401](#post-services-ocserv-enable-401) | Unauthorized | Unauthorized | + + +### Disable Pleroma (*PostServicesPleromaDisable*) + +``` +POST /services/pleroma/disable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-pleroma-disable-200) | OK | Pleroma disabled | +| [401](#post-services-pleroma-disable-401) | Unauthorized | Unauthorized | + +### Enable Pleroma (*PostServicesPleromaEnable*) + +``` +POST /services/pleroma/enable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-pleroma-enable-200) | OK | Pleroma enabled | +| [401](#post-services-pleroma-enable-401) | Unauthorized | Unauthorized | + + +### Enable SSH (*PostServicesSSHEnable*) + +``` +POST /services/ssh/enable +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#post-services-ssh-enable-200) | OK | SSH enabled | +| [401](#post-services-ssh-enable-401) | Unauthorized | Unauthorized | + +### Add SSH key to the user (*PostServicesSSHKeysUsername*) + +``` +POST /services/ssh/keys/{username} +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| username | `path` | string | `string` | | ✓ | | User to add keys for | +| public_key | `body` | [PostServicesSSHKeysUsernameBody](#post-services-ssh-keys-username-body) | `PostServicesSSHKeysUsernameBody` | | ✓ | | | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [201](#post-services-ssh-keys-username-201) | Created | SSH key added | +| [401](#post-services-ssh-keys-username-401) | Unauthorized | Unauthorized | +| [404](#post-services-ssh-keys-username-404) | Not Found | User not found | +| [409](#post-services-ssh-keys-username-409) | Conflict | Key already exists | + +###### Inlined models + +** PostServicesSSHKeysUsernameBody** + + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| public_key | string| `string` | ✓ | | | | + + + +### Create a new user (*PostUsers*) + +``` +POST /users +``` + +#### Consumes + * application/json + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| user | `body` | [PostUsersBody](#post-users-body) | `PostUsersBody` | | ✓ | | User to create | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [201](#post-users-201) | Created | Created user | +| [400](#post-users-400) | Bad Request | Bad request | +| [401](#post-users-401) | Unauthorized | Unauthorized | +| [409](#post-users-409) | Conflict | User already exists | + + +###### Inlined models + +** PostUsersBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| password | string| `string` | ✓ | | Unix password. | | +| username | string| `string` | ✓ | | Unix username. Must be alphanumeric and less than 32 characters | | + + + +### Set the new key for backblaze (*PutServicesResticBackblazeConfig*) + +``` +PUT /services/restic/backblaze/config +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| backblazeSettings | `body` | [PutServicesResticBackblazeConfigBody](#put-services-restic-backblaze-config-body) | `PutServicesResticBackblazeConfigBody` | | ✓ | | New Backblaze settings | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#put-services-restic-backblaze-config-200) | OK | New Backblaze settings | +| [400](#put-services-restic-backblaze-config-400) | Bad Request | Bad request | +| [401](#put-services-restic-backblaze-config-401) | Unauthorized | Unauthorized | + + +###### Inlined models + +** PutServicesResticBackblazeConfigBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| accountId | string| `string` | ✓ | | | | +| accountKey | string| `string` | ✓ | | | | +| bucket | string| `string` | ✓ | | | | + + + +### Initiate a new restic backup (*PutServicesResticBackupCreate*) + +``` +PUT /services/restic/backup/create +``` + +#### Security Requirements + * bearerAuth + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#put-services-restic-backup-create-200) | OK | Backup creation has started | +| [400](#put-services-restic-backup-create-400) | Bad Request | Bad request | +| [401](#put-services-restic-backup-create-401) | Unauthorized | Unauthorized | +| [409](#put-services-restic-backup-create-409) | Conflict | Backup already in progress | + +### Start backup restoration (*PutServicesResticBackupRestore*) + +``` +PUT /services/restic/backup/restore +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| backup | `body` | [PutServicesResticBackupRestoreBody](#put-services-restic-backup-restore-body) | `PutServicesResticBackupRestoreBody` | | ✓ | | Backup to restore | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#put-services-restic-backup-restore-200) | OK | Backup restoration process started | +| [400](#put-services-restic-backup-restore-400) | Bad Request | Bad request | +| [401](#put-services-restic-backup-restore-401) | Unauthorized | Unauthorized | + + +###### Inlined models + +** PutServicesResticBackupRestoreBody** + + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| backupId | string| `string` | ✓ | | | | + + + +### Change SSH settings (*PutServicesSSH*) + +``` +PUT /services/ssh +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| sshSettings | `body` | [PutServicesSSHBody](#put-services-ssh-body) | `PutServicesSSHBody` | | ✓ | | SSH settings | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#put-services-ssh-200) | OK | New settings saved | +| [400](#put-services-ssh-400) | Bad Request | Bad request | + + +###### Inlined models + +** PutServicesSSHBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| enable | boolean| `bool` | ✓ | | | | +| passwordAuthentication | boolean| `bool` | ✓ | | | | + + + +### Add a SSH root key (*PutServicesSSHKeySend*) + +``` +PUT /services/ssh/key/send +``` + +#### Consumes + * application/json + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| body | `body` | [PutServicesSSHKeySendBody](#put-services-ssh-key-send-body) | `PutServicesSSHKeySendBody` | | ✓ | | Public key to add | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [201](#put-services-ssh-key-send-201) | Created | Key added | +| [400](#put-services-ssh-key-send-400) | Bad Request | Bad request | +| [401](#put-services-ssh-key-send-401) | Unauthorized | Unauthorized | +| [409](#put-services-ssh-key-send-409) | Conflict | Key already exists | + + +###### Inlined models + +** PutServicesSSHKeySendBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| public_key | string| `string` | ✓ | | ssh-ed25519 public key. | | + + + +### Change system auto upgrade settings (*PutSystemConfigurationAutoUpgrade*) + +``` +PUT /system/configuration/autoUpgrade +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| autoUpgrade | `body` | [PutSystemConfigurationAutoUpgradeBody](#put-system-configuration-auto-upgrade-body) | `PutSystemConfigurationAutoUpgradeBody` | | ✓ | | Auto upgrade settings | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#put-system-configuration-auto-upgrade-200) | OK | New settings saved | +| [400](#put-system-configuration-auto-upgrade-400) | Bad Request | Bad request | + +###### Inlined models + +** PutSystemConfigurationAutoUpgradeBody** + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| allowReboot | boolean| `bool` | ✓ | | | | +| enable | boolean| `bool` | ✓ | | | | + + + +### Change system timezone (*PutSystemConfigurationTimezone*) + +``` +PUT /system/configuration/timezone +``` + +#### Security Requirements + * bearerAuth + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +|------|--------|------|---------|-----------| :------: |---------|-------------| +| timezone | `body` | [PutSystemConfigurationTimezoneBody](#put-system-configuration-timezone-body) | `PutSystemConfigurationTimezoneBody` | | ✓ | | Timezone to set | + +#### All responses +| Code | Status | Description | +|------|--------|-------------| +| [200](#put-system-configuration-timezone-200) | OK | Timezone changed | +| [400](#put-system-configuration-timezone-400) | Bad Request | Bad request | + +###### Inlined models + +** PutSystemConfigurationTimezoneBody** +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +|------|------|---------|:--------:| ------- |-------------|---------| +| timezone | string| `string` | ✓ | | | | diff --git a/src/rest-api/auth.md b/src/rest-api/auth.md new file mode 100644 index 0000000..17257a2 --- /dev/null +++ b/src/rest-api/auth.md @@ -0,0 +1 @@ +# Authorization diff --git a/src/rest-api/changelog.md b/src/rest-api/changelog.md new file mode 100644 index 0000000..7c2ea4a --- /dev/null +++ b/src/rest-api/changelog.md @@ -0,0 +1,70 @@ +# Changelog +## authorization_tokens branch +- Added authorization tokens module to allow + - Having more than one device controlling the server + - Refreshing the current token + - Obtaining a recovery token +### API changes +- +## 1.1.1 +Released on 26 Jan 2022 + +- Added [[migrations|migration module]] which handles one-shot actions which cannot be done by nixos-configuration. +- Added [[migrations#Fix NixOS configuration branch|migration]] which changes rolling-testing branch to master, bug introduced in 0.4.0 version of the app. +## 1.1.0 +Released on 9 Dec 2021 + +- Added system configuration endpoints. +- SSH management. +- Backups controller. +- Systemd is now used for system rebuilds. +- `WriteUserData` and `ReadUserData` utils added to reduce boilerplate of file locking. +- Unit tests are now a thing. +### API changes +- `/system/upgrade` is now `/system/configuration/upgrade`. +- `/api/version` added. +- `/services/ssh` added. +- `/services/ssh/` added. +- `/configuration/timezone` added. +- `/configuration/autoUpgrade` added. +- `/restic/backblaze/config` added. +- `/system/configuration/pull` added. +- `/services/restic/backup/reload` added. +--- +# Pre-1.1.0 changes +This is an API refactoring stage. There was no endpoint to retrieve API version, but these all were referenced as 1.1.0 version in code. + +## [Input sanitization, added swagger](https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api/pulls/5) +Released on 17 Nov 2021 + +- **Addressed [[vulnerabilities#SPCVE-0001|SPCVE-0001]].** +- Added Swagger documentation. + +## [Add basic API auth](https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api/pulls/4) +Released on 16 Nov 2021 + +- Added basic token auth. +## [Move to JSON controlled server settings](https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api/pulls/3) +Released on 16 Nov 2021 + +- **Assumes server already moved to JSON-controlled Nix config**. +- System is now configured by usage of userdata.json. +- File locking is used now. +## [Decomposition](https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api/pulls/2) +Released on 12 Nov 2021 +### API changes +* `/systemVersion` is now `/system/version`. +* `/getDKIM` is now `/services/mailserver/dkim`. +* `/pythonVersion` is now `/system/version/pythonVersion`. +* `/users/create` is now `POST` on `/users`. +* `/users/deleteUser` is now `DELETE` on `/users`. +* `/services/SERVICE_NAME/enable` and `/services/SERVICE_NAME/disable` now also return message in their responses. +* `/services/ssh/key/send`: response field `result` renamed to `status`. +### Other changes +* Moved to Python 3.9. +* Moved to `flask_restful`'s `Resource` objects. +* `distutils` is [deprecated](https://docs.python.org/3/whatsnew/3.10.html#distutils-deprecated), moved to `setuptools`. +### Code formatting +[Black](https://github.com/psf/black) is used for code *formatting*. + +No *linting* rules applied yet. \ No newline at end of file diff --git a/src/rest-api/migrations.md b/src/rest-api/migrations.md new file mode 100644 index 0000000..87f2085 --- /dev/null +++ b/src/rest-api/migrations.md @@ -0,0 +1,66 @@ +# Migrations +Migrations module is introduced in [[changelog#1 1 1|v1.1.1]] of API and provides one-shot migrations which cannot be performed from the NixOS configuration file changes. +These migrations are checked and ran before every start of the API. + +You can disable certain migrations if needed by creating an array at `api.skippedMigrations` in `userdata.json` and populating it with IDs of the migrations to skip. Adding `DISABLE_ALL` to that array disables the migrations module entirely. + +For example: +```json +... + "api": { + "token": "secret_token", + "enableSwagger": false, + "skippedMigrations": [ "fix_nixos_config_branch", "create_tokens_json" ] + }, +... +``` + +## Fix NixOS configuration branch +**Migration ID**: `fix_nixos_config_branch` + +**Introduced in**: [[changelog#1 1 1|v1.1.1]] + +### Description +Mobile SelfPrivacy app introduced a bug in version 0.4.0. +New servers were initialized with a rolling-testing nixos config branch. +This was fixed in app version 0.4.2, but existing servers were not updated. +This migration fixes this by changing the nixos config branch to master. + +### Run conditions +Git repository at `/etc/nixos` is using `rolling-testing` branch. + +### Migration process +1. Moving context to `/etc/nixos`. +2. Running `git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*` to fix the consequences of `--single-branch` flag. +3. `git fetch --all` to fetch all existing branches. +4. `git pull` to pull them. +5. `git checkout master` moves to master. +6. Leaving the context. + +## Create tokens JSON file +**Migration ID**: `create_tokens_json` + +**Introduced in**: [[changelog#authorization_tokens branch]] + +### Description +Selfprivacy API used a single token in userdata.json for authentication. +This migration creates a new tokens.json file with the old token in it. + +### Run conditions +`/etc/nixos/userdata/tokens.json` does not exist. + +### Migration process +1. Current token is retrieved from `userdata.json`. +2. `tokens.json` is created with 0600 permission. +3. File is populated with the following data: +```json +{ + "tokens": [ + { + "token": "token_string", + "name": "primary_token", + "date": "current date from str(datetime.now())", + } + ] +} +``` diff --git a/src/rest-api/testing.md b/src/rest-api/testing.md new file mode 100644 index 0000000..ee9c522 --- /dev/null +++ b/src/rest-api/testing.md @@ -0,0 +1,9 @@ +# Testing +We use pytest. +`coverage run -m pytest && coverage xml && coverage report` +# Code formatting +[Black](https://github.com/psf/black). +# Security +[Bandit](https://github.com/PyCQA/bandit). +# Linting +Pylint is recommended, but not enforced right now. \ No newline at end of file diff --git a/src/rest-api/vulnerabilities.md b/src/rest-api/vulnerabilities.md new file mode 100644 index 0000000..265ebc3 --- /dev/null +++ b/src/rest-api/vulnerabilities.md @@ -0,0 +1,22 @@ +# SPCVE-0001 +**API versions affected**: [[changelog#Input sanitization added swagger 17 Nov 2021 https git selfprivacy org SelfPrivacy selfprivacy-rest-api pulls 5|All pre-1.1.0 releases]] + +**SelfPrivacy app versions affected:** ≤0.2.4; fixed in 0.3.0 + +**Discovered on**: 16 Nov 2021 + +**Addressed on**: 17 Nov 2021 +## Description +Remote code execution vulnerability allowed root access to anyone, without any authorization. Was caused by the following factors: +- API had no authentication. +- No input sanitation used. +- Python's ``subprocess.Popen`` was called with `shell=True`. + +At that time, there was no mechanism to upgrade API, so the server had to be recreated. + +## Taken measures +- Basic API auth added. +- All `subprocess` calls now don't use `shell=true`. +- CI pipeline now includes [bandit](https://github.com/PyCQA/bandit) to prevent same mistakes in the future. +- More input sanitation added. +- Created a [nix overlay](https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nix-repo) to provide API upgrades automatically. \ No newline at end of file