[pve-devel] [Patch V2 acme 09/12] Add function setup and teardown.
Fabian Grünbichler
f.gruenbichler at proxmox.com
Wed Apr 1 15:28:19 CEST 2020
On March 31, 2020 12:08 pm, Wolfgang Link wrote:
> These are the two main functions that a plugin should offer.
> Setup creates the endpoint at which Letsencrypt does the validation, teardown does the cleanup.
>
> Signed-off-by: Wolfgang Link <w.link at proxmox.com>
> ---
> src/PVE/ACME.pm | 43 ++++++++++++++++++++++++++++++++++++++
> src/PVE/ACME/StandAlone.pm | 16 +++++---------
> 2 files changed, 48 insertions(+), 11 deletions(-)
>
> diff --git a/src/PVE/ACME.pm b/src/PVE/ACME.pm
> index 114eb41..c10dca2 100644
> --- a/src/PVE/ACME.pm
> +++ b/src/PVE/ACME.pm
> @@ -23,6 +23,9 @@ file_set_contents
> file_get_contents
> );
>
> +use PVE::ACME::Challenge;
> +use PVE::ACME::StandAlone;
> +
> Crypt::OpenSSL::RSA->import_random_seed();
>
> my $LETSENCRYPT_STAGING = 'https://acme-staging-v02.api.letsencrypt.org/directory';
> @@ -493,6 +496,46 @@ sub request_challenge_validation {
> return $return;
> }
>
> +# Setup the challange
> +# At the moment two plugin types are supproted
s/supproted/supported
> +# standalone: start an webserver an wait for the challenge
> +# dns: add an txt record over the given API
technically not true yet at this point, but not that important ;)
> +sub setup {
> + my ($acme, $auth, $node_config) = @_;
I'd rather pass in a hash like described in the comment to the patch
that calls this, although I have to say I am still not 100% convinced we
even need this here.
my $plugin_conf = cfs_read_file('priv/acme_plugins.cfg');
foreach $auth
my $domain = $auth->{identifier}->{value};
my $domain_info = $hash->{$domain};
die if !$domain_info;
my $plugin_id = $domain_info->{plugin} // 'default';
my $plugin_data = $plugin_conf->{ids}->{$plugin_id};
die if !$plugin_data;
my $plugin = PVE::ACME::Challenge->lookup($plugin_data->{tpye};
$plugin->setup($acme, $auth, $domain_info->{alias} // $domain, $plugin_data);
is short enough, and only needed in one place $order_certificate (in
pve-manager)
> +
> + my $fqdn = $auth->{identifier}->{value};
> + my $plugin_data = {};
> + my $plugin_type = "standalone";
> + my $plugin_conf = PVE::ACME::Challenge->load_config();
> +
> + # default is standalone if no plugin is set (old config)
> + my $index = 0;
> + while (defined($node_config->{$index})) {
> + if ($node_config->{$index}->{domain} eq $fqdn &&
> + defined($node_config->{$index}->{plugin})) {
> + $plugin_data = $plugin_conf->{ids}->{$node_config->{$index}->{plugin}};
> + $plugin_type = $plugin_data->{type};
> +
> + # Alias mode is only supported for DNSChallange
> + $plugin_data->{alias} = $node_config->{$index}->{alias} if
> + $node_config->{$index}->{alias};
> + last;
> + }
> + $index++;
> + }
> + die if $plugin_type eq "standalone";
> + my $plugin = PVE::ACME::Challenge->lookup($plugin_data->{type});
> + return $plugin->setup($acme, $auth, $plugin_data);
> +}
> +
> +#
> +#
> +sub teardown {
> + my ($self) = @_;
this is a misuse - $self refers to a blessed plugin here, not to an
instance of PVE::ACME.. should be dropped as well, see above.
> +
> + $self->teardown();
> +}
> +
> # actually 'do' a $method request on $url
> # $data: input for JWS, optional
> # $use_jwk: use JWK instead of KID in JWD (see sub jws)
> diff --git a/src/PVE/ACME/StandAlone.pm b/src/PVE/ACME/StandAlone.pm
> index ac75184..8fc8dc9 100644
> --- a/src/PVE/ACME/StandAlone.pm
> +++ b/src/PVE/ACME/StandAlone.pm
> @@ -31,15 +31,8 @@ sub options {
> sub setup {
> my ($class, $acme, $authorization) = @_;
since this patch adds a new parameter, it would be good to add it here
as well to keep the signatures in sync.
>
> - my $challenges = $authorization->{challenges};
> - die "no challenges defined in authorization\n" if !$challenges;
> -
> - my $http_challenges = [ grep {$_->{type} eq 'http-01'} @$challenges ];
> - die "no http-01 challenge defined in authorization\n"
> - if ! scalar $http_challenges;
> -
> - my $http_challenge = $http_challenges->[0];
> -
> + print "Setting up webserver\n";
could add $domain to this message if passed in?
> + my $http_challenge = PVE::ACME::extract_challenge($authorization->{challenges}, "http-01");
> die "no token found in http-01 challenge\n" if !$http_challenge->{token};
>
> my $key_authorization = $acme->key_authorization($http_challenge->{token});
> @@ -47,7 +40,7 @@ sub setup {
> my $server = HTTP::Daemon->new(
> LocalPort => 80,
> ReuseAddr => 1,
> - ) or die "Failed to initialize HTTP daemon\n";
> + ) or die "Failed to initialize HTTP daemon\n";
> my $pid = fork() // die "Failed to fork HTTP daemon - $!\n";
> if ($pid) {
> my $self = {
> @@ -62,7 +55,8 @@ sub setup {
> } else {
> while (my $c = $server->accept()) {
> while (my $r = $c->get_request()) {
> - if ($r->method() eq 'GET' and $r->uri->path eq "/.well-known/acme-challenge/$http_challenge->{token}") {
> + if ($r->method() eq 'GET' and
> + $r->uri->path eq "/.well-known/acme-challenge/$http_challenge->{token}") {
> my $resp = HTTP::Response->new(200, 'OK', undef, $key_authorization);
> $resp->request($r);
> $c->send_response($resp);
> --
> 2.20.1
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
>
>
More information about the pve-devel
mailing list