Compare commits

..

11 Commits

Author SHA1 Message Date
a91dcb144d Use model for db defaults as sqlite doesn't support them 2021-09-09 08:12:50 +10:00
e7f7be2a2b OpenIDC: Trigger the change event of the "restrict users" toggle when enabling/disabling oidc.
If this is not triggered and the OIDC toggle is enabled, the "disabled" property will be removed from the restricted user list input, causing an error when trying to submit the form without it.
2021-09-09 08:12:50 +10:00
076d89b5b5 Use localized strings for the OpenID Connect texts. 2021-09-09 08:12:50 +10:00
8539930f89 Updated the docs to add a section about OpenID Connect 2021-09-09 08:12:50 +10:00
87d9babbd3 Fix conditionals in the liquid template for OpenID Connect conf. 2021-09-09 08:12:50 +10:00
9f2d3a1737 Manually set the default values for the OpenID Connect columns.
There is a Knex issue ( https://github.com/knex/knex/issues/2649 ) that prevents .defaultTo from working for text columns.
2021-09-09 08:12:50 +10:00
daf399163c Allow limiting OpenID Connect auth to a list of users. 2021-09-09 08:12:50 +10:00
cdf702e545 Add a field to specify a list of allowed emails when using OpenID Connect auth. 2021-09-09 08:12:50 +10:00
5811345050 Use OpenResty instead of plain nginx to support OpenID Connect authorization. 2021-09-09 08:12:48 +10:00
53792a5cf7 Add database columns to store OpenID Connect information for Proxy Hosts. 2021-09-09 08:12:19 +10:00
8e10b7da37 Add UI tab for specifying OpenID Connect options for proxy hosts. 2021-09-09 08:12:19 +10:00
31 changed files with 1059 additions and 745 deletions

View File

@ -1 +1 @@
2.9.11
2.9.8

View File

@ -1,7 +1,7 @@
<p align="center">
<img src="https://nginxproxymanager.com/github.png">
<br><br>
<img src="https://img.shields.io/badge/version-2.9.11-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.9.8-green.svg?style=for-the-badge">
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
</a>
@ -483,30 +483,6 @@ Special thanks to the following contributors:
<br /><sub><b>Florian Meinicke</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ssrahul96">
<img src="https://avatars.githubusercontent.com/u/15570570?v=4" width="80" alt=""/>
<br /><sub><b>Rahul Somasundaram</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/BjoernAkAManf">
<img src="https://avatars.githubusercontent.com/u/833043?v=4" width="80" alt=""/>
<br /><sub><b>Björn Heinrichs</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/realJoshByrnes">
<img src="https://avatars.githubusercontent.com/u/204185?v=4" width="80" alt=""/>
<br /><sub><b>Josh Byrnes</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bergi9">
<img src="https://avatars.githubusercontent.com/u/5556750?v=4" width="80" alt=""/>
<br /><sub><b>bergi9</b></sub>
</a>
</td>
</tr>
</table>
<!-- markdownlint-enable -->

View File

@ -75,7 +75,7 @@ app.use(function (err, req, res, next) {
// Not every error is worth logging - but this is good for now until it gets annoying.
if (typeof err.stack !== 'undefined' && err.stack) {
if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
if (process.env.NODE_ENV === 'development') {
log.debug(err.stack);
} else if (typeof err.public == 'undefined' || !err.public) {
log.warn(err.message);

View File

@ -114,7 +114,7 @@ const internalCertificate = {
data.owner_user_id = access.token.getUserId(1);
if (data.provider === 'letsencrypt') {
data.nice_name = data.domain_names.join(', ');
data.nice_name = data.domain_names.sort().join(', ');
}
return certificateModel
@ -869,7 +869,7 @@ const internalCertificate = {
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
const prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
const prepareCmd = 'pip install ' + dns_plugin.package_name + '==' + dns_plugin.package_version + ' ' + dns_plugin.dependencies;
// Whether the plugin has a --<name>-credentials argument
const hasConfigArg = certificate.meta.dns_provider !== 'route53';

View File

@ -0,0 +1,48 @@
const migrate_name = 'openid_connect';
const logger = require('../logger').migrate;
/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.up = function (knex/*, Promise*/) {
logger.info('[' + migrate_name + '] Migrating Up...');
return knex.schema.table('proxy_host', function (proxy_host) {
proxy_host.integer('openidc_enabled').notNull().unsigned().defaultTo(0);
proxy_host.text('openidc_redirect_uri').notNull().defaultTo('');
proxy_host.text('openidc_discovery').notNull().defaultTo('');
proxy_host.text('openidc_auth_method').notNull().defaultTo('');
proxy_host.text('openidc_client_id').notNull().defaultTo('');
proxy_host.text('openidc_client_secret').notNull().defaultTo('');
})
.then(() => {
logger.info('[' + migrate_name + '] proxy_host Table altered');
});
};
/**
* Undo Migrate
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.down = function (knex/*, Promise*/) {
return knex.schema.table('proxy_host', function (proxy_host) {
proxy_host.dropColumn('openidc_enabled');
proxy_host.dropColumn('openidc_redirect_uri');
proxy_host.dropColumn('openidc_discovery');
proxy_host.dropColumn('openidc_auth_method');
proxy_host.dropColumn('openidc_client_id');
proxy_host.dropColumn('openidc_client_secret');
})
.then(() => {
logger.info('[' + migrate_name + '] proxy_host Table altered');
});
};

View File

@ -0,0 +1,40 @@
const migrate_name = 'openid_allowed_users';
const logger = require('../logger').migrate;
/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.up = function (knex/*, Promise*/) {
logger.info('[' + migrate_name + '] Migrating Up...');
return knex.schema.table('proxy_host', function (proxy_host) {
proxy_host.integer('openidc_restrict_users_enabled').notNull().unsigned().defaultTo(0);
proxy_host.json('openidc_allowed_users').notNull().defaultTo([]);
})
.then(() => {
logger.info('[' + migrate_name + '] proxy_host Table altered');
});
};
/**
* Undo Migrate
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.down = function (knex/*, Promise*/) {
return knex.schema.table('proxy_host', function (proxy_host) {
proxy_host.dropColumn('openidc_restrict_users_enabled');
proxy_host.dropColumn('openidc_allowed_users');
})
.then(() => {
logger.info('[' + migrate_name + '] proxy_host Table altered');
});
};

View File

@ -20,12 +20,23 @@ class ProxyHost extends Model {
this.domain_names = [];
}
// Default for openidc_allowed_users
if (typeof this.openidc_allowed_users === 'undefined') {
this.openidc_allowed_users = [];
}
// Default for meta
if (typeof this.meta === 'undefined') {
this.meta = {};
}
// Openidc defaults
if (typeof this.openidc_auth_method === 'undefined') {
this.openidc_auth_method = 'client_secret_post';
}
this.domain_names.sort();
this.openidc_allowed_users.sort();
}
$beforeUpdate () {
@ -35,6 +46,11 @@ class ProxyHost extends Model {
if (typeof this.domain_names !== 'undefined') {
this.domain_names.sort();
}
// Sort openidc_allowed_users
if (typeof this.openidc_allowed_users !== 'undefined') {
this.openidc_allowed_users.sort();
}
}
static get name () {
@ -46,7 +62,7 @@ class ProxyHost extends Model {
}
static get jsonAttributes () {
return ['domain_names', 'meta', 'locations'];
return ['domain_names', 'meta', 'locations', 'openidc_allowed_users'];
}
static get relationMappings () {

View File

@ -25,7 +25,7 @@
"mysql": "^2.18.1",
"node-rsa": "^1.0.8",
"nodemon": "^2.0.2",
"objection": "^2.2.16",
"objection": "^2.1.3",
"path": "^0.12.7",
"pg": "^7.12.1",
"restler": "^3.4.0",

View File

@ -153,7 +153,7 @@
"example": "john@example.com",
"format": "email",
"type": "string",
"minLength": 6,
"minLength": 8,
"maxLength": 100
},
"password": {
@ -235,6 +235,43 @@
"description": "Should we cache assets",
"example": true,
"type": "boolean"
},
"openidc_enabled": {
"description": "Is OpenID Connect authentication enabled",
"example": true,
"type": "boolean"
},
"openidc_redirect_uri": {
"type": "string"
},
"openidc_discovery": {
"type": "string"
},
"openidc_auth_method": {
"type": "string",
"pattern": "^(client_secret_basic|client_secret_post)$"
},
"openidc_client_id": {
"type": "string"
},
"openidc_client_secret": {
"type": "string"
},
"openidc_restrict_users_enabled": {
"description": "Only allow a specific set of OpenID Connect emails to access the resource",
"example": true,
"type": "boolean"
},
"openidc_allowed_users": {
"type": "array",
"minItems": 0,
"items": {
"type": "string",
"description": "Email Address",
"example": "john@example.com",
"format": "email",
"minLength": 1
}
}
}
}

View File

@ -64,6 +64,30 @@
"advanced_config": {
"type": "string"
},
"openidc_enabled": {
"$ref": "../definitions.json#/definitions/openidc_enabled"
},
"openidc_redirect_uri": {
"$ref": "../definitions.json#/definitions/openidc_redirect_uri"
},
"openidc_discovery": {
"$ref": "../definitions.json#/definitions/openidc_discovery"
},
"openidc_auth_method": {
"$ref": "../definitions.json#/definitions/openidc_auth_method"
},
"openidc_client_id": {
"$ref": "../definitions.json#/definitions/openidc_client_id"
},
"openidc_client_secret": {
"$ref": "../definitions.json#/definitions/openidc_client_secret"
},
"openidc_restrict_users_enabled": {
"$ref": "../definitions.json#/definitions/openidc_restrict_users_enabled"
},
"openidc_allowed_users": {
"$ref": "../definitions.json#/definitions/openidc_allowed_users"
},
"enabled": {
"$ref": "../definitions.json#/definitions/enabled"
},
@ -161,6 +185,30 @@
"advanced_config": {
"$ref": "#/definitions/advanced_config"
},
"openidc_enabled": {
"$ref": "#/definitions/openidc_enabled"
},
"openidc_redirect_uri": {
"$ref": "#/definitions/openidc_redirect_uri"
},
"openidc_discovery": {
"$ref": "#/definitions/openidc_discovery"
},
"openidc_auth_method": {
"$ref": "#/definitions/openidc_auth_method"
},
"openidc_client_id": {
"$ref": "#/definitions/openidc_client_id"
},
"openidc_client_secret": {
"$ref": "#/definitions/openidc_client_secret"
},
"openidc_restrict_users_enabled": {
"$ref": "#/definitions/openidc_restrict_users_enabled"
},
"openidc_allowed_users": {
"$ref": "#/definitions/openidc_allowed_users"
},
"enabled": {
"$ref": "#/definitions/enabled"
},
@ -251,6 +299,30 @@
"advanced_config": {
"$ref": "#/definitions/advanced_config"
},
"openidc_enabled": {
"$ref": "#/definitions/openidc_enabled"
},
"openidc_redirect_uri": {
"$ref": "#/definitions/openidc_redirect_uri"
},
"openidc_discovery": {
"$ref": "#/definitions/openidc_discovery"
},
"openidc_auth_method": {
"$ref": "#/definitions/openidc_auth_method"
},
"openidc_client_id": {
"$ref": "#/definitions/openidc_client_id"
},
"openidc_client_secret": {
"$ref": "#/definitions/openidc_client_secret"
},
"openidc_restrict_users_enabled": {
"$ref": "#/definitions/openidc_restrict_users_enabled"
},
"openidc_allowed_users": {
"$ref": "#/definitions/openidc_allowed_users"
},
"enabled": {
"$ref": "#/definitions/enabled"
},
@ -324,6 +396,30 @@
"advanced_config": {
"$ref": "#/definitions/advanced_config"
},
"openidc_enabled": {
"$ref": "#/definitions/openidc_enabled"
},
"openidc_redirect_uri": {
"$ref": "#/definitions/openidc_redirect_uri"
},
"openidc_discovery": {
"$ref": "#/definitions/openidc_discovery"
},
"openidc_auth_method": {
"$ref": "#/definitions/openidc_auth_method"
},
"openidc_client_id": {
"$ref": "#/definitions/openidc_client_id"
},
"openidc_client_secret": {
"$ref": "#/definitions/openidc_client_secret"
},
"openidc_restrict_users_enabled": {
"$ref": "#/definitions/openidc_restrict_users_enabled"
},
"openidc_allowed_users": {
"$ref": "#/definitions/openidc_allowed_users"
},
"enabled": {
"$ref": "#/definitions/enabled"
},

View File

@ -175,7 +175,7 @@ const setupCertbotPlugins = () => {
certificates.map(function (certificate) {
if (certificate.meta && certificate.meta.dns_challenge === true) {
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
const packages_to_install = `${dns_plugin.package_name}==${dns_plugin.package_version} ${dns_plugin.dependencies}`;
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);

View File

@ -1,5 +1,5 @@
location {{ path }} {
set $upstream {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}$request_uri;
set $upstream {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;

View File

@ -0,0 +1,47 @@
{% if openidc_enabled == 1 or openidc_enabled == true -%}
access_by_lua_block {
local openidc = require("resty.openidc")
local opts = {
redirect_uri = "{{- openidc_redirect_uri -}}",
discovery = "{{- openidc_discovery -}}",
token_endpoint_auth_method = "{{- openidc_auth_method -}}",
client_id = "{{- openidc_client_id -}}",
client_secret = "{{- openidc_client_secret -}}",
scope = "openid email profile"
}
local res, err = openidc.authenticate(opts)
if err then
ngx.status = 500
ngx.say(err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
{% if openidc_restrict_users_enabled == 1 or openidc_restrict_users_enabled == true -%}
local function contains(table, val)
for i=1,#table do
if table[i] == val then
return true
end
end
return false
end
local allowed_users = {
{% for user in openidc_allowed_users %}
"{{ user }}",
{% endfor %}
}
if not contains(allowed_users, res.id_token.email) then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
{% endif -%}
ngx.req.set_header("X-OIDC-SUB", res.id_token.sub)
ngx.req.set_header("X-OIDC-EMAIL", res.id_token.email)
ngx.req.set_header("X-OIDC-NAME", res.id_token.name)
}
{% endif %}

View File

@ -51,7 +51,8 @@ proxy_http_version 1.1;
{% endif %}
{% include "_hsts.conf" %}
{% include "_openid_connect.conf" %}
{% include "_hsts.conf" %}
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
proxy_set_header Upgrade $http_upgrade;

View File

@ -77,10 +77,10 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.6:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0:
version "6.12.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706"
integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
@ -2572,12 +2572,12 @@ object.pick@^1.2.0, object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
objection@^2.2.16:
version "2.2.16"
resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.16.tgz#552ec6d625a7f80d6e204fc63732cbd3fc56f31c"
integrity sha512-sq8erZdxW5ruPUK6tVvwDxyO16U49XAn/BmOm2zaNhNA2phOPCe2/7+R70nDEF1SFrgJOrwDu/PtoxybuJxnjQ==
objection@^2.1.3:
version "2.2.2"
resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.2.tgz#1a3c9010270e3677940d2bc91aeaeb3c0f103800"
integrity sha512-+1Ap7u9NQRochzDW5/BggUlKi94JfZGTJwQJuNXo8DwmAb8czEirvxcWBcX91/MmQq0BQUJjM4RPSiZhnkkWQw==
dependencies:
ajv "^6.12.6"
ajv "^6.12.0"
db-errors "^0.2.3"
on-finished@~2.3.0:

View File

@ -3,4 +3,3 @@ non-interactive = True
webroot-path = /data/letsencrypt-acme-challenge
key-type = ecdsa
elliptic-curve = secp384r1
preferred-chain = ISRG Root X1

View File

@ -1,9 +1,8 @@
set $upstream $forward_scheme://$server:$port$request_uri;
add_header X-Served-By $host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass $upstream;
proxy_pass $forward_scheme://$server:$port;

View File

@ -43,6 +43,16 @@ http {
proxy_cache_path /var/lib/nginx/cache/public levels=1:2 keys_zone=public-cache:30m max_size=192m;
proxy_cache_path /var/lib/nginx/cache/private levels=1:2 keys_zone=private-cache:5m max_size=1024m;
lua_package_path '~/lua/?.lua;;';
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 5;
# cache for discovery metadata documents
lua_shared_dict discovery 1m;
# cache for JWKs
lua_shared_dict jwks 1m;
log_format proxy '[$time_local] $upstream_cache_status $upstream_status $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] [Sent-to $server] "$http_user_agent" "$http_referer"';
log_format standard '[$time_local] $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] "$http_user_agent" "$http_referer"';

View File

@ -172,3 +172,26 @@ value by specifying it as a Docker environment variable. The default if not spec
X_FRAME_OPTIONS: "sameorigin"
...
```
## OpenID Connect SSO
You can secure any of your proxy hosts with OpenID Connect authentication, providing SSO support from an identity provider like Azure AD or KeyCloak. OpenID Connect support is provided through the [`lua-resty-openidc`](https://github.com/zmartzone/lua-resty-openidc) library of [`OpenResty`](https://github.com/openresty/openresty).
You will need a few things to get started with OpenID Connect:
- A registered application with your identity provider, they will provide you with a `Client ID` and a `Client Secret`. Public OpenID Connect applications (without a client secret) are not yet supported.
- A redirect URL to send the users to after they login with the identity provider, this can be any unused URL under the proxy host, like `https://<proxy host url>/private/callback`, the server will take care of capturing that URL and redirecting you to the proxy host root. You will need to add this URL to the list of allowed redirect URLs for the application you registered with your identity provider.
- The well-known discovery endpoint of the identity provider you want to use, this is an URL usually with the form `https://<provider URL>/.well-known/openid-configuration`.
After you have all this you can proceed to configure the proxy host with OpenID Connect authentication.
You can also add some rudimentary access control through a list of allowed emails in case your identity provider doesn't let you do that, if this option is enabled, any email not on that list will be denied access to the proxied host.
The proxy adds some headers based on the authentication result from the identity provider:
- `X-OIDC-SUB`: The subject identifier, according to the OpenID Coonect spec: `A locally unique and never reassigned identifier within the Issuer for the End-User`.
- `X-OIDC-EMAIL`: The email of the user that logged in, as specified in the `id_token` returned from the identity provider. The same value that will be checked for the email whitelist.
- `X-OIDC-NAME`: The user's name claim from the `id_token`, please note that not all id tokens necessarily contain this claim.

View File

@ -443,7 +443,7 @@
"normalize-url": "^5.1.0",
"npm-run-path": "^4.0.1",
"nprogress": "^0.2.0",
"nth-check": "^2.0.1",
"nth-check": "^1.0.2",
"num2fraction": "^1.2.2",
"number-is-nan": "^2.0.0",
"oauth-sign": "^0.9.0",
@ -612,7 +612,7 @@
"serve-index": "^1.9.1",
"serve-static": "^1.14.1",
"set-blocking": "^2.0.0",
"set-value": "^4.0.1",
"set-value": "^3.0.2",
"setimmediate": "^1.0.5",
"setprototypeof": "^1.2.0",
"sha.js": "^2.4.11",

View File

@ -1624,9 +1624,9 @@ ansi-regex@^4.1.0:
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
ansi-regex@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-styles@^2.2.1:
version "2.2.1"
@ -6726,13 +6726,6 @@ nth-check@^1.0.2, nth-check@~1.0.1:
dependencies:
boolbase "~1.0.0"
nth-check@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==
dependencies:
boolbase "^1.0.0"
num2fraction@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
@ -7706,9 +7699,9 @@ pretty-time@^1.1.0:
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
prismjs@^1.13.0, prismjs@^1.20.0:
version "1.25.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
version "1.24.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.24.0.tgz#0409c30068a6c52c89ef7f1089b3ca4de56be2ac"
integrity sha512-SqV5GRsNqnzCL8k5dfAjCNhUrF3pR0A9lTDSCUZeh/LIshheXJEaP0hwLz2t4XHivd2J/v2HR+gRnigzeKe3cQ==
private@^0.1.8:
version "0.1.8"
@ -8443,20 +8436,13 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
set-value@^3.0.0:
set-value@^3.0.0, set-value@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-3.0.2.tgz#74e8ecd023c33d0f77199d415409a40f21e61b90"
integrity sha512-npjkVoz+ank0zjlV9F47Fdbjfj/PfXyVhZvGALWsyIYU/qrMzpi6avjKW3/7KeSU2Df3I46BrN1xOI1+6vW0hA==
dependencies:
is-plain-object "^2.0.4"
set-value@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.0.1.tgz#bc23522ade2d52314ec3b5d6fb140f5cd3a88acf"
integrity sha512-ayATicCYPVnlNpFmjq2/VmVwhoCQA9+13j8qWp044fmFE3IFphosPtRM+0CJ5xoIx5Uy52fCcwg3XeH2pHbbPQ==
dependencies:
is-plain-object "^2.0.4"
setimmediate@^1.0.4, setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"

View File

@ -11,6 +11,7 @@
<li role="presentation" class="nav-item"><a href="#locations" aria-controls="tab4" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-layers"></i> <%- i18n('all-hosts', 'locations') %></a></li>
<li role="presentation" class="nav-item"><a href="#ssl-options" aria-controls="tab2" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-shield"></i> <%- i18n('str', 'ssl') %></a></li>
<li role="presentation" class="nav-item"><a href="#advanced" aria-controls="tab3" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-settings"></i> <%- i18n('all-hosts', 'advanced') %></a></li>
<li role="presentation" class="nav-item"><a href="#openidc" aria-controls="tab3" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-settings"></i><%- i18n('proxy-hosts', 'oidc') %></a></li>
</ul>
<div class="tab-content">
@ -270,6 +271,71 @@
</div>
</div>
</div>
<!-- OpenID Connect -->
<div role="tabpanel" class="tab-pane" id="openidc">
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="openidc_enabled" value="1"<%- openidc_enabled ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'oidc-enabled') %></span>
</label>
</div>
</div>
<div class="col-sm-12 col-md-12 openidc">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-redirect-uri') %><span class="form-required">*</span></label>
<input type="text" name="openidc_redirect_uri" class="form-control text-monospace" placeholder="" value="<%- openidc_redirect_uri %>" autocomplete="off" maxlength="255" required>
</div>
</div>
<div class="col-sm-12 col-md-12 openidc">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-discovery-endpoint') %><span class="form-required">*</span></label>
<input type="text" name="openidc_discovery" class="form-control text-monospace" placeholder="" value="<%- openidc_discovery %>" autocomplete="off" maxlength="255" required>
</div>
</div>
<div class="col-sm-12 col-md-12 openidc">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-token-auth-method') %><span class="form-required">*</span></label>
<select name="openidc_auth_method" class="form-control custom-select" placeholder="client_secret_post">
<option value="client_secret_post" <%- openidc_auth_method === 'client_secret_post' ? 'selected' : '' %>>client_secret_post</option>
<option value="client_secret_basic" <%- openidc_auth_method === 'client_secret_basic' ? 'selected' : '' %>>client_secret_basic</option>
</select>
</div>
</div>
<div class="col-sm-12 col-md-12 openidc">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-client-id') %><span class="form-required">*</span></label>
<input type="text" name="openidc_client_id" class="form-control text-monospace" placeholder="" value="<%- openidc_client_id %>" autocomplete="off" maxlength="255" required>
</div>
</div>
<div class="col-sm-12 col-md-12 openidc">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-client-secret') %><span class="form-required">*</span></label>
<input type="text" name="openidc_client_secret" class="form-control text-monospace" placeholder="" value="<%- openidc_client_secret %>" autocomplete="off" maxlength="255" required>
</div>
</div>
<div class="openidc">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="openidc_restrict_users_enabled" value="1"<%- openidc_restrict_users_enabled ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'oidc-allow-only-emails') %></span>
</label>
</div>
</div>
<div class="col-sm-12 col-md-12 openidc_users">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-allowed-emails') %><span class="form-required">*</span></label>
<input type="text" name="openidc_allowed_users" class="form-control" id="openidc_allowed_users" value="<%- openidc_allowed_users.join(',') %>" required>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>

View File

@ -21,29 +21,34 @@ module.exports = Mn.View.extend({
locationsCollection: new ProxyLocationModel.Collection(),
ui: {
form: 'form',
domain_names: 'input[name="domain_names"]',
forward_host: 'input[name="forward_host"]',
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
add_location_btn: 'button.add_location',
locations_container: '.locations_container',
le_error_info: '#le-error-info',
certificate_select: 'select[name="certificate_id"]',
access_list_select: 'select[name="access_list_id"]',
ssl_forced: 'input[name="ssl_forced"]',
hsts_enabled: 'input[name="hsts_enabled"]',
hsts_subdomains: 'input[name="hsts_subdomains"]',
http2_support: 'input[name="http2_support"]',
dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
dns_challenge_content: '.dns-challenge',
dns_provider: 'select[name="meta[dns_provider]"]',
credentials_file_content: '.credentials-file-content',
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
forward_scheme: 'select[name="forward_scheme"]',
letsencrypt: '.letsencrypt'
form: 'form',
domain_names: 'input[name="domain_names"]',
forward_host: 'input[name="forward_host"]',
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
add_location_btn: 'button.add_location',
locations_container: '.locations_container',
le_error_info: '#le-error-info',
certificate_select: 'select[name="certificate_id"]',
access_list_select: 'select[name="access_list_id"]',
ssl_forced: 'input[name="ssl_forced"]',
hsts_enabled: 'input[name="hsts_enabled"]',
hsts_subdomains: 'input[name="hsts_subdomains"]',
http2_support: 'input[name="http2_support"]',
dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
dns_challenge_content: '.dns-challenge',
dns_provider: 'select[name="meta[dns_provider]"]',
credentials_file_content: '.credentials-file-content',
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
forward_scheme: 'select[name="forward_scheme"]',
letsencrypt: '.letsencrypt',
openidc_enabled: 'input[name="openidc_enabled"]',
openidc_restrict_users_enabled: 'input[name="openidc_restrict_users_enabled"]',
openidc_allowed_users: 'input[name="openidc_allowed_users"]',
openidc: '.openidc',
openidc_users: '.openidc_users',
},
regions: {
@ -129,6 +134,27 @@ module.exports = Mn.View.extend({
}
},
'change @ui.openidc_enabled': function () {
let checked = this.ui.openidc_enabled.prop('checked');
if (checked) {
this.ui.openidc.show().find('input').prop('disabled', false);
} else {
this.ui.openidc.hide().find('input').prop('disabled', true);
}
this.ui.openidc_restrict_users_enabled.trigger('change');
},
'change @ui.openidc_restrict_users_enabled': function () {
let checked = this.ui.openidc_restrict_users_enabled.prop('checked');
if (checked) {
this.ui.openidc_users.show().find('input').prop('disabled', false);
} else {
this.ui.openidc_users.hide().find('input').prop('disabled', true);
}
},
'click @ui.add_location_btn': function (e) {
e.preventDefault();
@ -167,6 +193,14 @@ module.exports = Mn.View.extend({
data.hsts_enabled = !!data.hsts_enabled;
data.hsts_subdomains = !!data.hsts_subdomains;
data.ssl_forced = !!data.ssl_forced;
data.openidc_enabled = data.openidc_enabled === '1';
data.openidc_restrict_users_enabled = data.openidc_restrict_users_enabled === '1';
if (data.openidc_restrict_users_enabled) {
if (typeof data.openidc_allowed_users === 'string' && data.openidc_allowed_users) {
data.openidc_allowed_users = data.openidc_allowed_users.split(',');
}
}
if (typeof data.meta === 'undefined') data.meta = {};
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
@ -203,6 +237,12 @@ module.exports = Mn.View.extend({
data.certificate_id = parseInt(data.certificate_id, 10);
}
// OpenID Connect won't work with multiple domain names because the redirect URL has to point to a specific one
if (data.openidc_enabled && data.domain_names.length > 1) {
alert('Cannot use mutliple domain names when OpenID Connect is enabled');
return;
}
let method = App.Api.Nginx.ProxyHosts.create;
let is_new = true;
@ -344,6 +384,23 @@ module.exports = Mn.View.extend({
view.ui.certificate_select[0].selectize.setValue(view.model.get('certificate_id'));
}
});
// OpenID Connect
this.ui.openidc_allowed_users.selectize({
delimiter: ',',
persist: false,
maxOptions: 15,
create: function (input) {
return {
value: input,
text: input
};
}
});
this.ui.openidc.hide().find('input').prop('disabled', true);
this.ui.openidc_users.hide().find('input').prop('disabled', true);
this.ui.openidc_enabled.trigger('change');
this.ui.openidc_restrict_users_enabled.trigger('change');
},
initialize: function (options) {

View File

@ -1,8 +1,5 @@
<div class="container">
<div class="d-flex">
<button class="navbar-toggler d-lg-none mr-2" type="button" data-toggle="collapse" data-target="#menu">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="/">
<img src="/images/favicons/favicon-32x32.png" border="0"> &nbsp; <%- i18n('main', 'app') %>
</a>

View File

@ -1,11 +1,9 @@
<div class="page-main">
<div class="navbar-light">
<div class="header" id="header">
<!-- Header View -->
</div>
<div id="menu">
<!-- Menu View -->
</div>
<div class="header" id="header">
<!-- Header View -->
</div>
<div id="menu">
<!-- Menu View -->
</div>
<div class="my-3 my-md-5">
<div id="app-content" class="container">

View File

@ -130,7 +130,16 @@
"access-list": "Access List",
"allow-websocket-upgrade": "Websockets Support",
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL",
"custom-forward-host-help": "Add a path for sub-folder forwarding.\nExample: 203.0.113.25/path"
"custom-forward-host-help": "Use 1.1.1.1/path for sub-folder forwarding",
"oidc": "OpenID Connect",
"oidc-enabled": "Use OpenID Connect authentication",
"oidc-redirect-uri": "Redirect URI",
"oidc-discovery-endpoint": "Well-known discovery endpoint",
"oidc-token-auth-method": "Token endpoint auth method",
"oidc-client-id": "Client ID",
"oidc-client-secret": "Client secret",
"oidc-allow-only-emails": "Allow only these user emails",
"oidc-allowed-emails": "Allowed email addresses"
},
"redirection-hosts": {
"title": "Redirection Hosts",

View File

@ -22,6 +22,14 @@ const model = Backbone.Model.extend({
block_exploits: false,
http2_support: false,
advanced_config: '',
openidc_enabled: false,
openidc_redirect_uri: '',
openidc_discovery: '',
openidc_auth_method: 'client_secret_post',
openidc_client_id: '',
openidc_client_secret: '',
openidc_restrict_users_enabled: false,
openidc_allowed_users: [],
enabled: true,
meta: {},
// The following are expansions:

View File

@ -28,10 +28,10 @@
"messageformat-loader": "^0.8.1",
"mini-css-extract-plugin": "^0.9.0",
"moment": "^2.24.0",
"node-sass": "^6.0.1",
"node-sass": "^4.13.1",
"nodemon": "^2.0.2",
"numeral": "^2.0.6",
"sass-loader": "10.2.0",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3",
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
"underscore": "^1.12.1",

View File

@ -13,8 +13,8 @@ module.exports = {
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: `js/[name].bundle.js?v=${PACKAGE.version}`,
chunkFilename: `js/[name].bundle.[id].js?v=${PACKAGE.version}`,
filename: 'js/[name].bundle.js',
chunkFilename: 'js/[name].bundle.[id].js',
publicPath: '/'
},
resolve: {

File diff suppressed because it is too large Load Diff

View File

@ -9,10 +9,10 @@
* cloudflare: {
* display_name: "Name displayed to the user",
* package_name: "Package name in PyPi repo",
* version_requirement: "Optional package version requirements (e.g. ==1.3 or >=1.2,<2.0, see https://www.python.org/dev/peps/pep-0440/#version-specifiers)",
* package_version: "Package version in PyPi repo",
* dependencies: "Additional dependencies, space separated (as you would pass it to pip install)",
* credentials: `Template of the credentials file`,
* full_plugin_name: "The full plugin name as used in the commandline with certbot, e.g. 'dns-njalla'",
* full_plugin_name: "The full plugin name as used in the commandline with certbot, including prefixes, e.g. 'certbot-dns-njalla:dns-njalla'",
* },
* ...
* }
@ -22,30 +22,30 @@
module.exports = {
//####################################################//
acmedns: {
display_name: 'ACME-DNS',
package_name: 'certbot-dns-acmedns',
version_requirement: '~=0.1.0',
dependencies: '',
credentials: `dns_acmedns_api_url = http://acmedns-server/
dns_acmedns_registration_file = /data/acme-registration.json`,
full_plugin_name: 'dns-acmedns',
display_name: 'ACME-DNS',
package_name: 'certbot-dns-acmedns',
package_version: '0.1.0',
dependencies: '',
credentials: `certbot_dns_acmedns:dns_acmedns_api_url = http://acmedns-server/
certbot_dns_acmedns:dns_acmedns_registration_file = /data/acme-registration.json`,
full_plugin_name: 'certbot-dns-acmedns:dns-acmedns',
},
aliyun: {
display_name: 'Aliyun',
package_name: 'certbot-dns-aliyun',
version_requirement: '~=0.38.1',
dependencies: '',
credentials: `dns_aliyun_access_key = 12345678
dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`,
full_plugin_name: 'dns-aliyun',
display_name: 'Aliyun',
package_name: 'certbot-dns-aliyun',
package_version: '0.38.1',
dependencies: '',
credentials: `certbot_dns_aliyun:dns_aliyun_access_key = 12345678
certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`,
full_plugin_name: 'certbot-dns-aliyun:dns-aliyun',
},
//####################################################//
azure: {
display_name: 'Azure',
package_name: 'certbot-dns-azure',
version_requirement: '~=1.2.0',
dependencies: '',
credentials: `# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.
display_name: 'Azure',
package_name: 'certbot-dns-azure',
package_version: '1.2.0',
dependencies: '',
credentials: `# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.
# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.
# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.
@ -67,21 +67,21 @@ dns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf274462
},
//####################################################//
cloudflare: {
display_name: 'Cloudflare',
package_name: 'certbot-dns-cloudflare',
// version_requirement: '', // Official plugin, no version requirement
dependencies: 'cloudflare',
credentials: `# Cloudflare API token
display_name: 'Cloudflare',
package_name: 'certbot-dns-cloudflare',
package_version: '1.8.0',
dependencies: 'cloudflare',
credentials: `# Cloudflare API token
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
full_plugin_name: 'dns-cloudflare',
},
//####################################################//
cloudns: {
display_name: 'ClouDNS',
package_name: 'certbot-dns-cloudns',
version_requirement: '~=0.4.0',
dependencies: '',
credentials: `# Target user ID (see https://www.cloudns.net/api-settings/)
display_name: 'ClouDNS',
package_name: 'certbot-dns-cloudns',
package_version: '0.4.0',
dependencies: '',
credentials: `# Target user ID (see https://www.cloudns.net/api-settings/)
dns_cloudns_auth_id=1234
# Alternatively, one of the following two options can be set:
# dns_cloudns_sub_auth_id=1234
@ -93,153 +93,139 @@ dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
},
//####################################################//
cloudxns: {
display_name: 'CloudXNS',
package_name: 'certbot-dns-cloudxns',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
display_name: 'CloudXNS',
package_name: 'certbot-dns-cloudxns',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
dns_cloudxns_secret_key = 1122334455667788`,
full_plugin_name: 'dns-cloudxns',
},
//####################################################//
corenetworks: {
display_name: 'Core Networks',
package_name: 'certbot-dns-corenetworks',
version_requirement: '~=0.1.4',
dependencies: '',
credentials: `dns_corenetworks_username = asaHB12r
dns_corenetworks_password = secure_password`,
full_plugin_name: 'dns-corenetworks',
display_name: 'Core Networks',
package_name: 'certbot-dns-corenetworks',
package_version: '0.1.4',
dependencies: '',
credentials: `certbot_dns_corenetworks:dns_corenetworks_username = asaHB12r
certbot_dns_corenetworks:dns_corenetworks_password = secure_password`,
full_plugin_name: 'certbot-dns-corenetworks:dns-corenetworks',
},
//####################################################//
cpanel: {
display_name: 'cPanel',
package_name: 'certbot-dns-cpanel',
version_requirement: '~=0.2.2',
dependencies: '',
credentials: `cpanel_url = https://cpanel.example.com:2083
cpanel_username = user
cpanel_password = hunter2`,
full_plugin_name: 'cpanel',
},
//####################################################//
desec: {
display_name: 'deSEC',
package_name: 'certbot-dns-desec',
version_requirement: '~=0.3.0',
dependencies: '',
credentials: `dns_desec_token = YOUR_DESEC_API_TOKEN
dns_desec_endpoint = https://desec.io/api/v1/`,
full_plugin_name: 'dns-desec',
display_name: 'cPanel',
package_name: 'certbot-dns-cpanel',
package_version: '0.2.2',
dependencies: '',
credentials: `certbot_dns_cpanel:cpanel_url = https://cpanel.example.com:2083
certbot_dns_cpanel:cpanel_username = user
certbot_dns_cpanel:cpanel_password = hunter2`,
full_plugin_name: 'certbot-dns-cpanel:cpanel',
},
//####################################################//
duckdns: {
display_name: 'DuckDNS',
package_name: 'certbot-dns-duckdns',
version_requirement: '~=0.6',
dependencies: '',
credentials: 'dns_duckdns_token=your-duckdns-token',
full_plugin_name: 'dns-duckdns',
display_name: 'DuckDNS',
package_name: 'certbot-dns-duckdns',
package_version: '0.6',
dependencies: '',
credentials: 'dns_duckdns_token=your-duckdns-token',
full_plugin_name: 'dns-duckdns',
},
//####################################################//
digitalocean: {
display_name: 'DigitalOcean',
package_name: 'certbot-dns-digitalocean',
// version_requirement: '', // Official plugin, no version requirement
package_version: '1.8.0',
dependencies: '',
credentials: 'dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff',
full_plugin_name: 'dns-digitalocean',
},
//####################################################//
directadmin: {
display_name: 'DirectAdmin',
package_name: 'certbot-dns-directadmin',
version_requirement: '~=0.0.23',
dependencies: '',
credentials: `directadmin_url = https://my.directadminserver.com:2222
display_name: 'DirectAdmin',
package_name: 'certbot-dns-directadmin',
package_version: '0.0.20',
dependencies: '',
credentials: `directadmin_url = https://my.directadminserver.com:2222
directadmin_username = username
directadmin_password = aSuperStrongPassword`,
full_plugin_name: 'directadmin',
full_plugin_name: 'certbot-dns-directadmin:directadmin',
},
//####################################################//
dnsimple: {
display_name: 'DNSimple',
package_name: 'certbot-dns-dnsimple',
// version_requirement: '', // Official plugin, no version requirement
package_version: '1.8.0',
dependencies: '',
credentials: 'dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw',
full_plugin_name: 'dns-dnsimple',
},
//####################################################//
dnsmadeeasy: {
display_name: 'DNS Made Easy',
package_name: 'certbot-dns-dnsmadeeasy',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
display_name: 'DNS Made Easy',
package_name: 'certbot-dns-dnsmadeeasy',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
full_plugin_name: 'dns-dnsmadeeasy',
},
//####################################################//
dnspod: {
display_name: 'DNSPod',
package_name: 'certbot-dns-dnspod',
version_requirement: '~=0.1.0',
dependencies: '',
credentials: `dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL"
dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
full_plugin_name: 'dns-dnspod',
display_name: 'DNSPod',
package_name: 'certbot-dns-dnspod',
package_version: '0.1.0',
dependencies: '',
credentials: `certbot_dns_dnspod:dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL"
certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
full_plugin_name: 'certbot-dns-dnspod:dns-dnspod',
},
//####################################################//
dynu: {
display_name: 'Dynu',
package_name: 'certbot-dns-dynu',
version_requirement: '~=0.0.1',
dependencies: '',
credentials: 'dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN',
full_plugin_name: 'dns-dynu',
display_name: 'Dynu',
package_name: 'certbot-dns-dynu',
package_version: '0.0.1',
dependencies: '',
credentials: 'certbot_dns_dynu:dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN',
full_plugin_name: 'certbot-dns-dynu:dns-dynu',
},
//####################################################//
eurodns: {
display_name: 'EuroDNS',
package_name: 'certbot-dns-eurodns',
version_requirement: '~=0.0.4',
dependencies: '',
credentials: `dns_eurodns_applicationId = myuser
display_name: 'EuroDNS',
package_name: 'certbot-dns-eurodns',
package_version: '0.0.4',
dependencies: '',
credentials: `dns_eurodns_applicationId = myuser
dns_eurodns_apiKey = mysecretpassword
dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`,
full_plugin_name: 'dns-eurodns',
full_plugin_name: 'certbot-dns-eurodns:dns-eurodns',
},
//####################################################//
gandi: {
display_name: 'Gandi Live DNS',
package_name: 'certbot_plugin_gandi',
version_requirement: '~=1.3.2',
dependencies: '',
credentials: `# live dns v5 api key
dns_gandi_api_key=APIKEY
# optional organization id, remove it if not used
dns_gandi_sharing_id=SHARINGID`,
full_plugin_name: 'dns-gandi',
display_name: 'Gandi Live DNS',
package_name: 'certbot_plugin_gandi',
package_version: '1.2.5',
dependencies: '',
credentials: 'certbot_plugin_gandi:dns_api_key = APIKEY',
full_plugin_name: 'certbot-plugin-gandi:dns',
},
//####################################################//
godaddy: {
display_name: 'GoDaddy',
package_name: 'certbot-dns-godaddy',
version_requirement: '~=0.2.0',
dependencies: '',
credentials: `dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567
display_name: 'GoDaddy',
package_name: 'certbot-dns-godaddy',
package_version: '0.2.0',
dependencies: '',
credentials: `dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567
dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`,
full_plugin_name: 'dns-godaddy',
},
//####################################################//
google: {
display_name: 'Google',
package_name: 'certbot-dns-google',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `{
display_name: 'Google',
package_name: 'certbot-dns-google',
package_version: '1.8.0',
dependencies: '',
credentials: `{
"type": "service_account",
...
}`,
@ -247,156 +233,142 @@ dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`,
},
//####################################################//
hetzner: {
display_name: 'Hetzner',
package_name: 'certbot-dns-hetzner',
version_requirement: '~=1.0.4',
dependencies: '',
credentials: 'dns_hetzner_api_token = 0123456789abcdef0123456789abcdef',
full_plugin_name: 'dns-hetzner',
display_name: 'Hetzner',
package_name: 'certbot-dns-hetzner',
package_version: '1.0.4',
dependencies: '',
credentials: 'certbot_dns_hetzner:dns_hetzner_api_token = 0123456789abcdef0123456789abcdef',
full_plugin_name: 'certbot-dns-hetzner:dns-hetzner',
},
//####################################################//
infomaniak: {
display_name: 'Infomaniak',
package_name: 'certbot-dns-infomaniak',
version_requirement: '~=0.1.12',
dependencies: '',
credentials: 'dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
full_plugin_name: 'dns-infomaniak',
display_name: 'Infomaniak',
package_name: 'certbot-dns-infomaniak',
package_version: '0.1.12',
dependencies: '',
credentials: 'certbot_dns_infomaniak:dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
full_plugin_name: 'certbot-dns-infomaniak:dns-infomaniak',
},
//####################################################//
inwx: {
display_name: 'INWX',
package_name: 'certbot-dns-inwx',
version_requirement: '~=2.1.2',
dependencies: '',
credentials: `dns_inwx_url = https://api.domrobot.com/xmlrpc/
dns_inwx_username = your_username
dns_inwx_password = your_password
dns_inwx_shared_secret = your_shared_secret optional`,
full_plugin_name: 'dns-inwx',
display_name: 'INWX',
package_name: 'certbot-dns-inwx',
package_version: '2.1.2',
dependencies: '',
credentials: `certbot_dns_inwx:dns_inwx_url = https://api.domrobot.com/xmlrpc/
certbot_dns_inwx:dns_inwx_username = your_username
certbot_dns_inwx:dns_inwx_password = your_password
certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`,
full_plugin_name: 'certbot-dns-inwx:dns-inwx',
},
//####################################################//
ionos: {
display_name: 'IONOS',
package_name: 'certbot-dns-ionos',
version_requirement: '==2021.9.20.post1',
dependencies: '',
credentials: `dns_ionos_prefix = myapikeyprefix
dns_ionos_secret = verysecureapikeysecret
dns_ionos_endpoint = https://api.hosting.ionos.com`,
full_plugin_name: 'dns-ionos',
display_name: 'IONOS',
package_name: 'certbot-dns-ionos',
package_version: '0.0.7',
dependencies: '',
credentials: `certbot_dns_ionos:dns_ionos_prefix = myapikeyprefix
certbot_dns_ionos:dns_ionos_secret = verysecureapikeysecret
certbot_dns_ionos:dns_ionos_endpoint = https://api.hosting.ionos.com`,
full_plugin_name: 'certbot-dns-ionos:dns-ionos',
},
//####################################################//
ispconfig: {
display_name: 'ISPConfig',
package_name: 'certbot-dns-ispconfig',
version_requirement: '~=0.2.0',
dependencies: '',
credentials: `dns_ispconfig_username = myremoteuser
dns_ispconfig_password = verysecureremoteuserpassword
dns_ispconfig_endpoint = https://localhost:8080`,
full_plugin_name: 'dns-ispconfig',
display_name: 'ISPConfig',
package_name: 'certbot-dns-ispconfig',
package_version: '0.2.0',
dependencies: '',
credentials: `certbot_dns_ispconfig:dns_ispconfig_username = myremoteuser
certbot_dns_ispconfig:dns_ispconfig_password = verysecureremoteuserpassword
certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`,
full_plugin_name: 'certbot-dns-ispconfig:dns-ispconfig',
},
//####################################################//
isset: {
display_name: 'Isset',
package_name: 'certbot-dns-isset',
version_requirement: '~=0.0.3',
dependencies: '',
credentials: `dns_isset_endpoint="https://customer.isset.net/api"
dns_isset_token="<token>"`,
full_plugin_name: 'dns-isset',
display_name: 'Isset',
package_name: 'certbot-dns-isset',
package_version: '0.0.3',
dependencies: '',
credentials: `certbot_dns_isset:dns_isset_endpoint="https://customer.isset.net/api"
certbot_dns_isset:dns_isset_token="<token>"`,
full_plugin_name: 'certbot-dns-isset:dns-isset',
},
joker: {
display_name: 'Joker',
package_name: 'certbot-dns-joker',
version_requirement: '~=1.1.0',
dependencies: '',
credentials: `dns_joker_username = <Dynamic DNS Authentication Username>
dns_joker_password = <Dynamic DNS Authentication Password>
dns_joker_domain = <Dynamic DNS Domain>`,
full_plugin_name: 'dns-joker',
display_name: 'Joker',
package_name: 'certbot-dns-joker',
package_version: '1.1.0',
dependencies: '',
credentials: `certbot_dns_joker:dns_joker_username = <Dynamic DNS Authentication Username>
certbot_dns_joker:dns_joker_password = <Dynamic DNS Authentication Password>
certbot_dns_joker:dns_joker_domain = <Dynamic DNS Domain>`,
full_plugin_name: 'certbot-dns-joker:dns-joker',
},
//####################################################//
linode: {
display_name: 'Linode',
package_name: 'certbot-dns-linode',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
display_name: 'Linode',
package_name: 'certbot-dns-linode',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
dns_linode_version = [<blank>|3|4]`,
full_plugin_name: 'dns-linode',
},
//####################################################//
loopia: {
display_name: 'Loopia',
package_name: 'certbot-dns-loopia',
version_requirement: '~=1.0.0',
dependencies: '',
credentials: `dns_loopia_user = user@loopiaapi
display_name: 'Loopia',
package_name: 'certbot-dns-loopia',
package_version: '1.0.0',
dependencies: '',
credentials: `dns_loopia_user = user@loopiaapi
dns_loopia_password = abcdef0123456789abcdef01234567abcdef0123`,
full_plugin_name: 'dns-loopia',
},
//####################################################//
luadns: {
display_name: 'LuaDNS',
package_name: 'certbot-dns-luadns',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `dns_luadns_email = user@example.com
display_name: 'LuaDNS',
package_name: 'certbot-dns-luadns',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_luadns_email = user@example.com
dns_luadns_token = 0123456789abcdef0123456789abcdef`,
full_plugin_name: 'dns-luadns',
},
//####################################################//
netcup: {
display_name: 'netcup',
package_name: 'certbot-dns-netcup',
version_requirement: '~=1.0.0',
dependencies: '',
credentials: `dns_netcup_customer_id = 123456
dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
full_plugin_name: 'dns-netcup',
display_name: 'netcup',
package_name: 'certbot-dns-netcup',
package_version: '1.0.0',
dependencies: '',
credentials: `certbot_dns_netcup:dns_netcup_customer_id = 123456
certbot_dns_netcup:dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
certbot_dns_netcup:dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
full_plugin_name: 'certbot-dns-netcup:dns-netcup',
},
//####################################################//
njalla: {
display_name: 'Njalla',
package_name: 'certbot-dns-njalla',
version_requirement: '~=1.0.0',
dependencies: '',
credentials: 'dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
full_plugin_name: 'dns-njalla',
display_name: 'Njalla',
package_name: 'certbot-dns-njalla',
package_version: '1.0.0',
dependencies: '',
credentials: 'certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
full_plugin_name: 'certbot-dns-njalla:dns-njalla',
},
//####################################################//
nsone: {
display_name: 'NS1',
package_name: 'certbot-dns-nsone',
// version_requirement: '', // Official plugin, no version requirement
package_version: '1.8.0',
dependencies: '',
credentials: 'dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw',
full_plugin_name: 'dns-nsone',
},
//####################################################//
oci: {
display_name: 'Oracle Cloud Infrastructure DNS',
package_name: 'certbot-dns-oci',
package_version: '0.3.6',
dependencies: 'oci',
credentials: `[DEFAULT]
user = ocid1.user.oc1...
fingerprint = xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
tenancy = ocid1.tenancy.oc1...
region = us-ashburn-1
key_file = ~/.oci/oci_api_key.pem`,
full_plugin_name: 'dns-oci',
},
//####################################################//
ovh: {
display_name: 'OVH',
package_name: 'certbot-dns-ovh',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `dns_ovh_endpoint = ovh-eu
display_name: 'OVH',
package_name: 'certbot-dns-ovh',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = MDAwMDAwMDAwMDAw
dns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
@ -404,41 +376,41 @@ dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
},
//####################################################//
porkbun: {
display_name: 'Porkbun',
package_name: 'certbot-dns-porkbun',
version_requirement: '~=0.2',
dependencies: '',
credentials: `dns_porkbun_key=your-porkbun-api-key
display_name: 'Porkbun',
package_name: 'certbot-dns-porkbun',
package_version: '0.2',
dependencies: '',
credentials: `dns_porkbun_key=your-porkbun-api-key
dns_porkbun_secret=your-porkbun-api-secret`,
full_plugin_name: 'dns-porkbun',
},
//####################################################//
powerdns: {
display_name: 'PowerDNS',
package_name: 'certbot-dns-powerdns',
version_requirement: '~=0.2.0',
dependencies: '',
credentials: `dns_powerdns_api_url = https://api.mypowerdns.example.org
dns_powerdns_api_key = AbCbASsd!@34`,
full_plugin_name: 'dns-powerdns',
display_name: 'PowerDNS',
package_name: 'certbot-dns-powerdns',
package_version: '0.2.0',
dependencies: '',
credentials: `certbot_dns_powerdns:dns_powerdns_api_url = https://api.mypowerdns.example.org
certbot_dns_powerdns:dns_powerdns_api_key = AbCbASsd!@34`,
full_plugin_name: 'certbot-dns-powerdns:dns-powerdns',
},
//####################################################//
regru: {
display_name: 'reg.ru',
package_name: 'certbot-regru',
version_requirement: '~=1.0.2',
dependencies: '',
credentials: `certbot_regru:dns_username=username
display_name: 'reg.ru',
package_name: 'certbot-regru',
package_version: '1.0.2',
dependencies: '',
credentials: `certbot_regru:dns_username=username
certbot_regru:dns_password=password`,
full_plugin_name: 'certbot-regru:dns',
},
//####################################################//
rfc2136: {
display_name: 'RFC 2136',
package_name: 'certbot-dns-rfc2136',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `# Target DNS server
display_name: 'RFC 2136',
package_name: 'certbot-dns-rfc2136',
package_version: '1.8.0',
dependencies: '',
credentials: `# Target DNS server
dns_rfc2136_server = 192.0.2.1
# Target DNS port
dns_rfc2136_port = 53
@ -452,43 +424,42 @@ dns_rfc2136_algorithm = HMAC-SHA512`,
},
//####################################################//
route53: {
display_name: 'Route 53 (Amazon)',
package_name: 'certbot-dns-route53',
// version_requirement: '', // Official plugin, no version requirement
dependencies: '',
credentials: `[default]
display_name: 'Route 53 (Amazon)',
package_name: 'certbot-dns-route53',
package_version: '1.8.0',
dependencies: '',
credentials: `[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
full_plugin_name: 'dns-route53',
},
//####################################################//
transip: {
display_name: 'TransIP',
package_name: 'certbot-dns-transip',
version_requirement: '~=0.3.3',
dependencies: '',
credentials: `dns_transip_username = my_username
dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
full_plugin_name: 'dns-transip',
display_name: 'TransIP',
package_name: 'certbot-dns-transip',
package_version: '0.3.3',
dependencies: '',
credentials: `certbot_dns_transip:dns_transip_username = my_username
certbot_dns_transip:dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
full_plugin_name: 'certbot-dns-transip:dns-transip',
},
//####################################################//
vultr: {
display_name: 'Vultr',
package_name: 'certbot-dns-vultr',
version_requirement: '~=1.0.3',
dependencies: '',
credentials: 'dns_vultr_key = YOUR_VULTR_API_KEY',
full_plugin_name: 'dns-vultr',
display_name: 'Vultr',
package_name: 'certbot-dns-vultr',
package_version: '1.0.3',
dependencies: '',
credentials: 'certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY',
full_plugin_name: 'certbot-dns-vultr:dns-vultr',
},
//####################################################//
websupportsk: {
display_name: 'Websupport.sk',
package_name: 'certbot-dns-websupportsk',
version_requirement: '~=0.1.6',
dependencies: '',
credentials: `dns_websupportsk_api_key = <api_key>
dns_websupportsk_secret = <secret>
dns_websupportsk_domain = example.com`,
full_plugin_name: 'dns-websupportsk',
desec: {
display_name: 'deSEC',
package_name: 'certbot-dns-desec',
package_version: '0.3.0',
dependencies: '',
credentials: `certbot_dns_desec:dns_desec_token = YOUR_DESEC_API_TOKEN
certbot_dns_desec:dns_desec_endpoint = https://desec.io/api/v1/`,
full_plugin_name: 'certbot-dns-desec:dns-desec',
},
};