Current File : //scripts/migrate-pdns-conf
#!/usr/local/cpanel/3rdparty/bin/perl

#                                      Copyright 2024 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

package scripts::migrate_pdns_conf;

use strict;
use warnings;

use Try::Tiny;

use Pod::Usage               ();
use Getopt::Long             ();
use Cpanel::LoadFile         ();
use Cpanel::Exception        ();
use Cpanel::FileUtils::Write ();
use Cpanel::Rand::Get        ();
use Cpanel::PwCache          ();

my $CONF_FILE = '/etc/pdns/pdns.conf';

exit( __PACKAGE__->script( \@ARGV ) ) unless caller;

sub script {
    my ( $class, $argv ) = @_;

    die Cpanel::Exception::create('RootRequired')->to_string_no_id() unless ( $> == 0 && $< == 0 );
    my $self = bless { 'notify' => 1 }, $class;

    my $help;
    Getopt::Long::GetOptionsFromArray(
        $argv,
        'notify!'    => \$self->{'notify'},
        'dry-run'    => \$self->{'dry-run'},
        'man|help|h' => \$help,
    ) or return Pod::Usage::pod2usage( -exitval => 'NOEXIT', -output => \*STDERR, -verbose => 99, -sections => [qw(NAME DESCRIPTION SYNOPSIS)] );

    # -1 to get the right exit code
    return Pod::Usage::pod2usage( -exitval => 'NOEXIT', -output => \*STDOUT, -verbose => 99, -sections => [qw(NAME DESCRIPTION SYNOPSIS)] ) - 1 if $help;

    return _nofile() unless -e $CONF_FILE;

    my $current_conf = Cpanel::LoadFile::loadfileasarrayref($CONF_FILE);
    my $changes      = $self->migrate_conf($current_conf);
    $changes->{enabled} = $self->enable_settings($current_conf);

    return _nochanges() if !_has_changes($changes);

    _print_changes($changes);
    return 0 if $self->{'dry-run'};

    if ( _overwrite_and_fix_ownership( $CONF_FILE, join( '', @{$current_conf} ) ) ) {
        print "[+] Updated $CONF_FILE successfully\n";
        $self->send_notification($changes)
          if $self->{'notify'};
    }
    else {
        print "[!] Failed to update $CONF_FILE: $!\n";
        return 1;
    }

    return 0;
}

sub migrate_conf {
    my ( $self, $current_conf ) = @_;

    my $changes = {
        'removed' => [],
        'renamed' => [],
        'manual'  => [],
    };

    my @to_remove = qw/
      pipebackend-abi-version
      strict-rfc-axfrs
      send-root-referral
      experimental-lua-policy-script
      allow-recursion
      recursive-cache-ttl
      recursor
      api-readonly
      experimental-api-readonly
      api-logfile
      default-soa-mail
      default-soa-name
      soa-expire-default
      soa-minimum-ttl
      soa-refresh-default
      soa-retry-default
      /;
    my %remove_if_value_starts_with = (
        'local-ipv6' => '::',    #No longer force pdns to bind to ::
    );

    my %renamed = (
        'allow-dns-update-from'       => 'allow-dnsupdate-from',
        'allow-unsigned-supermaster'  => 'allow-unsigned-autoprimary',
        'experimental-json-interface' => 'api',
        'forward-dnsupdates'          => 'forward-dnsupdate',
        'local-ipv6-nonexist-fail'    => 'local-address-nonexist-fail',
        'master'                      => 'primary',
        'slave'                       => 'secondary',
        'slave-cycle-interval'        => 'xfr-cycle-interval',
        'slave-renotify'              => 'secondary-do-renotify',
        'superslave'                  => 'autosecondary',
        ( map { $_ => substr( $_, 0, -1 ) } qw{default-ksk-algorithms default-zsk-algorithms} ),
        ( map { $_ => substr( $_, 13 ) } qw{experimental-api-key experimental-dnsupdate experimental-dname-processing} ),
    );

    foreach my $line ( @{$current_conf} ) {
        next if $line =~ m/^\s*(#|$)/;

        # Parse it first to make life easier and run less regexes overall
        my ( $key, $value ) = $line =~ /^\s*([^=]+?)\s*=\s*(.*?)\s*$/;

        if ( my @remove = grep { $_ eq $key } @to_remove ) {
            push @{ $changes->{'removed'} }, @remove;
            $line = '#' . $line;
        }
        elsif ( exists( $remove_if_value_starts_with{$key} ) && index( $value, $remove_if_value_starts_with{$key} ) == 0 ) {
            push @{ $changes->{'removed'} }, "$key=$remove_if_value_starts_with{$key}";
            $line = '#' . $line;
        }
        elsif ( exists( $renamed{$key} ) ) {

            # Possibly could have made this conditional on array of things?
            # Anyways force list context as otherwise perl whines about it.
            if ( ( grep { $_ eq $key } qw{default-ksk-algorithms default-zsk-algorithms} ) && split( /,/, $value ) > 1 ) {
                $line = '#' . $line;
                push @{ $changes->{'manual'} }, $key;
                next;
            }
            push @{ $changes->{'renamed'} }, { $key => $renamed{$key} };
            $line = "$renamed{$key}=$value\n";
        }
    }

    return $changes;
}

sub enable_settings {
    my ( $self, $current_conf ) = @_;

    my @changes;

    my %to_enable = (
        'webserver'                  => 'yes',
        'api'                        => 'yes',
        'webserver-address'          => '127.0.0.1',
        'webserver-allow-from'       => '127.0.0.1,::1',
        'webserver-port'             => '953',
        'api-key'                    => undef,
        'webserver-password'         => undef,
        'bind-ignore-broken-records' => 'yes',
        'upgrade-unknown-types'      => '1',
    );

    my %seen_settings;

    foreach my $line ( @{$current_conf} ) {
        next if $line =~ m/^\s*(#|$)/;

        if ( $line =~ m{^\s*bind-dnssec-db\s*=\s*/etc/pdns/dnssec\.db\s*} ) {
            $line = "bind-dnssec-db=/var/cpanel/pdns/dnssec.db\n";
            push( @changes, { 'bind-dnssec-db' => '/var/cpanel/pdns/dnssec.db' } );
            next;
        }

        my ( $key, $value ) = ( $line =~ /^\s*([^\s=]+)\s*=\s*(\S+)?\s*$/ );
        next unless defined $key;
        next unless exists $to_enable{$key};

        # Remove duplicate, empty and templated values
        if ( $seen_settings{$key} || !defined($value) || ( $value eq '@@REPLACE@@' || $value eq '@@REPLACE_PASS@@' ) ) {
            $line = '';
            next;
        }

        $seen_settings{$key} = 1;

        # leave generated credentials as-is
        next if ( !defined( $to_enable{$key} ) );

        # leave correct settings alone
        next if ( $value eq $to_enable{$key} );

        # fix setting
        $line = "$key=$to_enable{$key}\n";
        push( @changes, { $key => $to_enable{$key} } );
    }

    # add missing settings
    foreach my $key ( keys %to_enable ) {
        next if $seen_settings{$key};
        push( @changes, { $key => ( $to_enable{$key} // '***HIDDEN***' ) } );
        $to_enable{$key} //= Cpanel::Rand::Get::getranddata(16);
        unshift( @{$current_conf}, "$key=$to_enable{$key}\n" );
    }

    return \@changes;
}

sub _has_changes {
    my $changes = shift;

    foreach my $type (qw/removed renamed manual enabled/) {
        return 1 if scalar @{ $changes->{$type} };
    }
    return 0;
}

sub _print_changes {
    my $changes = shift;

    foreach my $removed ( @{ $changes->{'removed'} } ) {
        print "[*] Deprecated directive: '$removed' will be disabled.\n";
    }
    foreach my $renamed ( @{ $changes->{'renamed'} } ) {
        print "[*] Renamed directive: '$_' will be updated to '$renamed->{$_}'.\n" foreach keys %{$renamed};
    }
    foreach my $manual ( @{ $changes->{'manual'} } ) {
        print "[*] Deprecated configuration: '$manual' will be disabled as this requires admin intervention.\n";
    }
    foreach my $enabled ( @{ $changes->{'enabled'} } ) {
        print "[*] New enabled settings: The '$_' directive was added and set to '$enabled->{$_}'.\n" foreach keys %{$enabled};
    }

    return 0;
}

sub _nochanges {
    print "[+] $CONF_FILE does not contain any directives that need to be updated.\n";
    return 0;
}

sub _nofile {
    print "[*] $CONF_FILE is not present on the system. Nothing to do.\n";
    return 0;
}

sub send_notification {
    my ( $self, $changes ) = @_;

    return if $ENV{'CPANEL_BASE_INSTALL'};    # Nothing is setup. it's meaningless to notify here.
    my $old = $self->_locale()->set_context_plain();

    require Cpanel::Notify;
    my $ic_obj = Cpanel::Notify::notification_class(
        'class'            => 'Check::PdnsConf',
        'application'      => 'Check::PdnsConf',
        'status'           => 1,
        'constructor_args' => [
            'origin'    => 'migrate-pdns-conf',
            'skip_send' => 1,
            %{$changes},
        ]
    );
    $ic_obj->send();

    $self->_locale()->set_context($old);
    return 1;
}

sub _locale {
    my ($self) = @_;
    require Cpanel::Locale;
    return ( $self->{'_locale'} ||= Cpanel::Locale->get_handle() );
}

sub _overwrite_and_fix_ownership {
    my ( $conf, $content ) = @_;

    my ( $named_uid, $named_gid ) = ( Cpanel::PwCache::getpwnam_noshadow('named') )[ 2, 3 ];
    my $overwrite_callback = sub {
        my $fh = shift;
        chmod( 0600, $fh );
        chown( $named_uid, $named_gid, $fh );
    };

    return Cpanel::FileUtils::Write::overwrite( $conf, $content, { before_installation => $overwrite_callback } );
}

1;

__END__

=pod

=encoding utf8

=head1 NAME

migrate-pdns-conf

=head1 DESCRIPTION

Utility to update PowerDNS configuration from v3.x to v4.1:

    * Deprecated options will be removed.
    * Renamed configuration directives will be updated to the new names.
    * New settings will be enabled.

=head1 SYNOPSIS

    migrate-pdns-conf [OPTIONS]

    OPTIONS:
    --notify    Send notification about changes made to System Administrator.
                Default: on
                To disable notifications, use --no-notify

    --dry-run   Do a dry-run without altering the file, or sending the notification.
                Prints the changes that would be made to screen.

    --help      This documentation.

=cut
Seguro Celular
Home business sonyw300 6 de febrero de 2020
SEGURO PARA CUALQUIER MOMENTO
Evita cualquier situación con nuestro seguro para celular.

Contar con un seguro para celular te brinda una protección integral contra situaciones comunes como robo, accidentes y pérdida. No solo te ahorrará dinero en reparaciones o reemplazos, sino que también te proporcionará la tranquilidad de saber que estás respaldado en caso de cualquier eventualidad. Es una inversión inteligente para salvaguardar tu dispositivo, tus datos y tu tranquilidad.

De viaje
Protegido siempre ante cualquier imprevisto
Contratar ahora!
Robo
Asegura tu equipo ante un posible robo
Contratar ahora!
Accidentes
No pases un mal momento, protege tu dispositivo
Contratar ahora!
Previous slide
Next slide
¿Porqué seguro celular es para ti?
Nos comprometemos en brindarte la mejor protección para tu dispositivo
Cobertura mundial

Sea cual sea el problema estamos aquí para proteger tu inversión y brindarte la tranquilidad que necesitas.

Proceso de reclamación fácil y rápido

Sabemos que necesitas una solución rápida en caso de cualquier incidente.

Opciones personalizadas:

Ofrecemos opciones flexibles que se adaptan a tus requisitos individuales.

Atención al cliente excepcional

Estamos disponible para responder y brindarte asistencia personalizada en todo momento.

Tu tranquilidad está a
solo un clic de distancia

Protege tu dispositivo de cualquier imprevisto
TESTIMONIOS
¿Qué dicen nuestros
valiosos clientes?
"¡Increíble servicio de seguro para celular! Rápido, eficiente y confiable. Mi reclamo fue procesado sin problemas y recibí un reemplazo de mi teléfono en tiempo récord. ¡Gracias por brindar una excelente protección para mis dispositivos!"
male1085054890319
Herman Miller
"Me encanta la tranquilidad que me brinda su servicio de seguro para celular. Sé que mi dispositivo está protegido contra cualquier daño accidental o robo. Además, el proceso de reclamación es sencillo. Super recomendado!
female1021755931884
Sofia Millan
"Me ha salvado en más de una ocasión. El personal siempre está dispuesto a ayudar y resolver cualquier problema que surja. Gracias a su servicio, puedo disfrutar de mi teléfono sin preocupaciones.
male20131085934506012
Alexander Rodriguez