Skip to content

Update config on certificate change #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 82 additions & 4 deletions inc/admin/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use function HM\ACM\update_cloudfront_distribution_config;
use function HM\ACM\unlink_certificate;
use function HM\ACM\unlink_cloudfront_distribution;
use function HM\ACM\distribution_matches_certificate;

function bootstrap() {
add_submenu_page( 'tools.php', __( 'HTTPS Certificate', 'hm-acm' ), __( 'HTTPS Certificate', 'hm-acm' ), 'manage_options', 'hm-acm', __NAMESPACE__ . '\\admin_page' );
Expand Down Expand Up @@ -120,7 +121,68 @@ function on_unlink_cloudfront_distribution() {
exit;
}

function admin_page() {
/**
* Display details of the certificate in an accordion to aid debugging.
*
* @return void
*/
function display_certificate_details() : void {

if( ! has_certificate() ) {
return;
}

printf(
'<details><summary><strong>%s</strong></summary><pre><code>%s</code></pre></details><br/>',
esc_html__( 'Certificate Details', 'hm-acm' ),
esc_html( print_r( get_certificate(), true ) )

);
}

/**
* Display details of the distribution in an accordion to aid debugging.
*
* @return void
*/
function display_cloudfront_distribution_details() : void {

$distribution = get_cloudfront_distribution();

if( empty( $distribution ) ) {
return;
}

printf(
'<details><summary><strong>%s</strong></summary><pre><code>%s</code></pre></details><br/>',
esc_html__( 'Cloudfront Distribution Details', 'hm-acm' ),
esc_html( print_r( $distribution, true ) )

);
}

/**
* Display the admin page content to administer certificate setup.
*
* @return void
*/
function admin_page() : void {

/**
* Determine whether or not to show the unlink certificate button.
*
* @param bool $show_unlink_certificate True if the unlink certificate button should be shown, otherwise false.
*/
$show_unlink_certificate = apply_filters( 'hm.acm.show_unlink_certificate', true );

/**
* Determine whether or not to show the unlink distribution button.
*
* @param bool $show_unlink_distribution True if the unlink distribution button should be shown, otherwise false.
*/
$show_unlink_distribution= apply_filters( 'hm.acm.show_unlink_distribution', true );


?>
<div class="wrap">
<h1><?php _e( 'HTTPS Certificate', 'hm-acm' ) ?></h1>
Expand All @@ -129,7 +191,13 @@ function admin_page() {
$certificate = get_certificate();
?>
<h4><?php printf( esc_html__( 'HTTPS Certificate: %1$s (%2$s)', 'hm-acm' ), implode( ', ', $certificate['SubjectAlternativeNames'] ), $certificate['Status'] ) ?></h4>
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hm-acm-action', 'unlink-certificate' ), 'hm-acm-unlink-certificate' ) ) ?>" class="button button-secondary"><?php esc_html_e( 'Unlink', 'hm-acm' ) ?></a>

<?php display_certificate_details(); ?>

<?php if ( $show_unlink_certificate ): ?>
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hm-acm-action', 'unlink-certificate' ), 'hm-acm-unlink-certificate' ) ) ?>" class="button button-secondary"><?php esc_html_e( 'Unlink', 'hm-acm' ) ?></a>
<?php endif ?>

<?php endif ?>
<?php if ( has_cloudfront_function() ) : ?>
<h4><?php printf( esc_html__( 'CDN Function: %s', 'hm-acm' ), get_cloudfront_function_arn() ) ?></h4>
Expand All @@ -144,7 +212,16 @@ function admin_page() {
$distribution = get_cloudfront_distribution();
?>
<h4><?php printf( esc_html__( 'CDN Distribution: %s', 'hm-acm' ), $distribution['Id'] ) ?></h4>
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hm-acm-action', 'unlink-cloudfront-distribution' ), 'hm-acm-unlink-cloudfront-distribution' ) ) ?>" class="button button-secondary"><?php esc_html_e( 'Unlink', 'hm-acm' ) ?></a>

<?php display_cloudfront_distribution_details(); ?>

<?php if( ! distribution_matches_certificate() ): ?>
<div class="notice notice-warning notice-alt"><p><?php esc_html_e( 'Warning: Your distribution is not using the linked certificate. Please update your config (below).', 'hm-acm' ) ?></p></div>
<?php endif ?>

<?php if ( $show_unlink_distribution ): ?>
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hm-acm-action', 'unlink-cloudfront-distribution' ), 'hm-acm-unlink-cloudfront-distribution' ) ) ?>" class="button button-secondary"><?php esc_html_e( 'Unlink', 'hm-acm' ) ?></a>
<?php endif ?>
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'hm-acm-action', 'update-cloudfront-distribution-config' ), 'hm-acm-update-cloudfront-distribution-config' ) ) ?>" class="button button-secondary">Update Config</a>
<p><?php esc_html_e( 'Please update the following DNS records to your domain(s) to activate HTTPS. If you want to support HTTPS on the root of your domain, you need to use AWS Route 53 with an "ALIAS" recording point the cloudfront domain listed below.' ) ?></p>
<table class="wp-list-table widefat fixed striped">
Expand All @@ -167,6 +244,7 @@ function admin_page() {
<?php endforeach ?>
</tbody>
</table>

<?php endif ?>
<?php if ( ! has_certificate() ) : ?>
<h2><?php esc_html_e( 'Step 1: Request HTTPS Certificate', 'hm-acm' ) ?></h2>
Expand All @@ -177,7 +255,7 @@ function admin_page() {
<input type="text" class="widefat" value="<?php echo esc_attr( implode( ', ', get_suggested_domains() ) ) ?>" name="domains" />
</p>
<p class="description">
<?php _e( 'Seperate multiple domains with a comma.' ) ?>
<?php _e( 'Separate multiple domains with a comma.' ) ?>
</p>
<p class="submit">
<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Request Certificate', 'hm-acm' ) ?>" />
Expand Down
54 changes: 54 additions & 0 deletions inc/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,56 @@

use Exception;

/**
* Check whether the site has a certificate set as an option.
*
* @return boolean True if the certificate is set.
*/
function has_certificate() : bool {
return (bool) get_option( 'hm-acm-certificate' );
}

/**
* Check whether the site's certificate has been verified.
*
* @return boolean True if the certificate is verified.
*/
function has_verified_certificate() {
return get_certificate()['Status'] === 'ISSUED';
}

/**
* Get the certificate details for the site.
*
* @return array An array of certificate details, derived from \AWS\Result.
*/
function get_certificate() : array {
return get_option( 'hm-acm-certificate' );
}

/**
* Check whether the distribution is using the linked certificate.
*
* @return bool True if certificates match, else false.
*/
function distribution_matches_certificate() : bool {

if( ! has_certificate() || ! has_cloudfront_distribution() ) {
return false;
}

$certificate = get_certificate();
$distribution = get_cloudfront_distribution();

return $certificate['CertificateArn'] === ( $distribution['DistributionConfig']['ViewerCertificate']['ACMCertificateArn'] ?? false );

}

/**
* Refresh the certificate from AWS and update the site option to match, or remove it on failure.
*
* @return void
*/
function refresh_certificate() {
try {
$certificate = get_aws_acm_client()->describeCertificate([
Expand Down Expand Up @@ -72,6 +110,12 @@ function create_certificate( array $domains ) : array {
return $certificate;
}

/**
* Unlink the certificate from the site by deleting the option.
* Note this does not delete the certificate from AWS.
*
* @return void
*/
function unlink_certificate() {
delete_option( 'hm-acm-certificate' );
}
Expand Down Expand Up @@ -115,6 +159,11 @@ function create_cloudfront_distribution() {
update_option( 'hm-cloudfront-distribution', $result['Distribution'] );
}

/**
* Update the existing Cloudfront distribution.
*
* @return void
*/
function update_cloudfront_distribution_config() {
$current_distribution = get_aws_cloudfront_client()->getDistribution([
'Id' => get_cloudfront_distribution()['Id'],
Expand Down Expand Up @@ -451,6 +500,11 @@ function get_aws_cloudfront_client() {
return get_aws_sdk()->createCloudFront();
}

/**
* Get the AWS instance for the network.
*
* @return \AWS\Sdk AWS SDK class for the network.
*/
function get_aws_sdk() {
static $sdk;
if ( $sdk ) {
Expand Down