Monday, June 26, 2023

Valid local self signed certs

While developing web sites/applications locally, to facilitate development, you often use a local host name, such as 127.0.0.1, localhost, site.local, example.test, or sub.company.local.  While you can access the site/application using normal HTTP, sometimes the application is configured for secure HTTP i.e. HTTPS or you always want to force HTTPS no matter the environment (dev/qa/prod).  


However, ‘made up’ local host names such as example.test, site.local, site.dev etc can not use an external ssl certificate, as they cannot be accessed remotely to verify authenticity by a certificate authority (CA).  So typically one would create a self signed certificate.  But over time, browsers have restricted the acceptance of self signed certificates, resulting in a less friendly or impossible developer workflow.  So the next step would be to add your own CA to your local environment, but that can be tedious and error prone. Luckily, there is a utility which greatly simplifies the process, for linux, macos, and even windows - mkcert


“Using certificates from real certificate authorities (CAs) for development can be dangerous or impossible (for hosts like example.test, localhost or 127.0.0.1), but self-signed certificates cause trust errors. Managing your own CA is the best solution, but usually involves arcane commands, specialized knowledge and manual steps.

mkcert automatically creates and installs a local CA in the system root store, and generates locally-trusted certificates. mkcert does not automatically configure servers to use the certificates, though, that's up to you.”

https://github.com/FiloSottile/mkcert


To creating a usable self signed ssl certificate using Windows, Nginx, and Laragon (a portable LAMP stack):


Download the latest mkcert for your OS (Windows in this case)

https://github.com/FiloSottile/mkcert/releases

mkcert-v1.4.1-windows-amd64.exe


Copy the file to a new dir

C:/laragon/bin/mkcert/

And rename to a generic mkcert.exe


Note, assuming you installed/extracted Laragon to C:/laragon


In a command window with Administrator Privileges (Run as Admin)

> cd C:\laragon\etc\ssl


Specify the destination of the CA cert

> mkdir C:\laragon\etc\ssl\mkcert


Set an temporary environment variable for mkcert to read

> setx CAROOT "C:\laragon\etc\ssl\mkcert"


By default, it would have be in you user directory

> C:\Users\<user>\AppData\Local\mkcert


Close the command window and re-open it so the environment variable can be read

In linux you might source ~/.bash_profile .. but windows


Test that the environment variable is indeed set

> cd C:\laragon\etc\ssl\

> echo %CAROOT%

C:\laragon\etc\ssl\mkcert


Create and install your local CA

> ..\..\bin\mkcert\mkcert -install


You will be shown a prompt warning you that you are doing what you want to do, add a local CA 


After reading, Click Yes


Note, by default the CA key will be named rootCA-key.pem and the CA cert will be named rootCA.pem. The names are hard coded in the project source main.go, if you want to compile the project.


You can view the CA via the Certificate Manager

Start Menu -> Run -> certmgr

Or

Laragon -> Menu -> Nginx -> Certificate Manager

Note, while Laragon does have its own CA which it can add, it does not seem to work with recent browser updates.


Click to Trusted Root Certification Authority -> Certificates

Scroll to find mkcert Computer\User@Computer


Note, you can delete it if you want by Right Clicking on and select Delete


Now generate the SSL certificate, which will be signed by the CA you just added


> cd C:\laragon\etc\ssl

> ..\..\bin\mkcert\mkcert site.local "*.site.local"

Would create the SSL key and cert in C:\laragon\etc\ssl as 

site.local+1-key.pem and site.local+1.pem 


Rename the files, or specify names when creating:


> ..\..\bin\mkcert\mkcert -key-file company.localhost.key -cert-file company.localhost.crt company.localhost *.company.localhost

Which would match

company.localhost

site1.company.localhost

site2.company.localhost


Or more generically


> ..\..\bin\mkcert\mkcert -key-file dev.localhost.key -cert-file dev.localhost.crt dev.localhost *.dev.localhost

Which would match

dev.localhost

site1.dev.localhost

site2.dev.localhost


Note, most browsers do not support wildcards 2 levels deep ie don't use just localhost or test


Note, Chrome redirects use of the .dev tld to HTTPS, as Google now owns the official .dev tld.  While using any domain name which you override in your /etc/hosts file should be ok, it is best to use a domain you actually own.  But if that is not practical, .test, .local, .localhost are the often provided alternatives.



Edit you Nginx or Apache config to add the SSL cert and key, and reload


Using the default website in Laragon as a working example 

C:\laragon\etc\nginx\sites-enabled\00-default.conf


    listen 8443;

    Server_name site1.dev.localhost;


    # Enable SSL

    ssl_certificate "C:/laragon/etc/ssl/dev.localhost.crt";

    ssl_certificate_key "C:/laragon/etc/ssl/dev.localhost.key";

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;

    ssl_prefer_server_ciphers on;



Note, if you are using Skype, you may not be able to run a webserver on port 443, so choose another port, such as 8443.


Assuming you have added your local host name to /etc/hosts or 

C:\Windows\system32\drivers\etc\hosts 

127.0.0.1       site1.dev.localhost


Viewing https://site1.dev.localhost 

Should result in a valid SSL cert.



Enjoy your HTTPS, and develop away.



To install reinstall on a computer, or reinstall after deleting the mkcert CA


Copy the full Laragon dir, or the rootCA.pem at least

Set an temporary environment variable for mkcert to read

> setx CAROOT "C:\laragon\etc\ssl\mkcert"

Close the command window, re-open

Create and install your local CA

> ..\..\bin\mkcert\mkcert -install 




FireFox

Mkcert auto installs into chromium based browsers.

For FireFox, there are a few extra steps.


View where mkcert installed the CA certificate

> mkcert -CAROOT


in FireFox url, type in about:preferences#privacy

Filter options to ‘certificates’

click View Certificates -> Authorities -> Import

Select the rootCA.pem file, in the directory listed by the prior mkcert -CAROOT


The above used to be sufficient, for newer FireFox versions >= 112

There is an extra step to take

Within the certificate list, find the imported cert in the list; it will be in the middle listed under ‘mkcert’

Now click the Edit Trust button, and check ‘enable for websites’



Re-enjoy your HTTPS, and develop away.



-End of Document-

Thanks for reading




Monday, May 22, 2023

Bash script to delete merged local git branches

When using git, overtime, your local copies of branches can grow and become burdensome to search through.  While you could manually delete 'old' branches, some of those branches may still be active eg not merged in yet.  It would be nice to have a bash script which would find merged branches older than N days and delete them.

First, list branches merged
> git branch --merged
# https://git-scm.com/docs/git

Then ensure to exclude your main branches: master, main, development
> git branch --merged | grep -v -E "\\*|\bmaster\b|\bmain\b|\bdevelopment\b"
# -v, --invert-match        select non-matching lines
# -E, --extended-regexp  \b word boundaries

Then to loop over those branches, use xargs to split the prior results
for k in $(git branch --merged | grep -v -E "\\*|\bmaster\b|\bmain\b|\bdevelopment\b" | xargs -r -n 1); do 
# xargs - build and execute command lines from standard input
# -n max-args, --max-args=max-args; exit if greater
# -r, --no-run-if-empty; do not run if no results

Then for each branch, see if it has commits greater than N days ago
> git log -1 --since="$days days ago" -s $k
# git log, one line, since $days days ago, for branch $k

If so, then delete the branch
> git branch -d $k


Full script below, with a confirmation prompt
#!/bin/bash

# delete merged local branches
days=90
found=0

# preview
# git branch --merged | grep -v -E "\\*|\bmaster\b|\bmain\b|\bdevelopment\b" | xargs -r -n 1

# list branches merged
# git branch --merged
# https://git-scm.com/docs/git-branch

# exclude master, main, development
# grep -v -E "\\*|\bmaster\b|\bmain\b|\bdevelopment\b"
# -v, --invert-match        select non-matching lines
# -E, --extended-regexp     \b word boundaries
# https://www.man7.org/linux/man-pages/man1/grep.1.html

# xargs -r -n 1
# -n max-args, --max-args=max-args; exit if greater
# -r, --no-run-if-empty; do not run if no results
# https://www.man7.org/linux/man-pages/man1/xargs.1.html

# git log -1 --since="$days days ago" -s $k
# gti log, one line, since $days days ago, for branch $k
# https://www.git-scm.com/docs/git-log

# delete branch
# git branch -d $k
# https://git-scm.com/docs/git-branch

echo "branches older than $days days:"
for k in $(git branch --merged | grep -v -E "\\*|\bmaster\b|\bmain\b|\bdevelopment\b" | xargs -r -n 1); do
  if [[ ! $(git log -1 --since="$days days ago" -s $k) ]]; then
    echo $k
    (( found++ ))
  fi
done

if [[ $found -eq 0 ]]; then
    echo "no branches found"
    exit 0
fi;

read -s -n 1 -p "press any key to delete $found branches older than $days days . . ."
echo ""

# run
for k in $(git branch --merged | grep -v -E "\\*|\bmaster\b|\bmain\b|\bdevelopment\b" | xargs -r -n 1); do
  if [[ ! $(git log -1 --since="$days days ago" -s $k) ]]; then
    git branch -d $k
  fi
done

Source: GitHub Gist

-End of Document-
Thanks for reading


Tuesday, March 28, 2023

Debug ReactJS with WebStorm

Instead of using console.logs, WebStorm can be used to debug your development builds of your React app. You can set breakpoints, and inspect your apps in real-time, greatly expediting and simplifying your debug experience.



WebStorm is an integrated development environment for JavaScript and related technologies. Like other JetBrains IDEs, it makes your development experience more enjoyable, automating routine work and helping you handle complex tasks with ease.

source: https://www.jetbrains.com/webstorm/


React is a declarative, efficient, and flexible JavaScript library for building user interfaces. ReactJS is an open-source, component-based front-end library responsible only for the view layer of the application. React is used to create modular user interfaces. It promotes the development of reusable UI components that display dynamic data.

source: https://www.geeksforgeeks.org/react-js-introduction-working/

source: https://react.dev



How To:

Open WebStorm, configure a JavaScript debugger

Run -> Edit Configurations

or 

Click the drop down near the run/debug icons, select Edit Configurations



Add a new configuration, click the + button

Choose JavaScript Debug

Change the url to match your development environment, often localhost:3000 

Save



Click the Debug icon, the green bug button, next to the green play button

WebStorm by default will launch a new Chrome instance

However, it will not have any of your plugins.

You can re-install all your plugins, or better, edit the browser configuration in WebStorm



Customize browser config

File -> Settings -> Tools -> Web Browsers and Preview

Edit Chrome

Enable Use custom user data dictionary, and past in the path to your Chrome user data directory

Windows %LOCALAPPDATA%\Google\Chrome\User Data

Mac OSX ~/Library/Application Support/Google/Chrome

Linux ~/.config/google-chrome

source: https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#Windows




Additional information from WebStorm

source: https://blog.jetbrains.com/webstorm/2017/01/debugging-react-apps/



-End of Document-

Thanks for reading


Monday, April 25, 2022

Exclude Code from Defender

If you are using Windows, or other OSes which have antivirus/malware scanners installed such as Windows Defender, you can increase the responsiveness and decrease the time taken for your code installs, transpiles, complies, etc by simply excluding your code from their scans.

Best practice, keep your versioned code in a common directory, such as

C:/Users/[user]/My Documents/ado/[repo-name]

or 

C:/dev/git/[repo-name]


And then simply exclude that directory from your antivirus/malware scanner(s).

An example for Windows Defender on Windows 10

 

After excluding your code directory, code installs such as npm, composer, nuget, maven, etc will not take as long and use much less resources eg cpu, disk i/o.

-End of Document-
Thanks for reading

Monday, March 21, 2022

PHPStan - static analysis of PHP code

 'PHPStan finds bugs in your code without writing tests.' https://phpstan.org/

PHPStan performs static code analysis on your code.

Static analysis is the method of testing your code for basic logical, runtime or typographical exceptions without actually executing the code or accessing external services like databases

Static analysis of your codebase happens relatively fast since the code doesn't actually get executed but scanned for common errors, like having a method that doesn't return the expected date type.

PHPStan checks for a couple of language constructs such as use of instanceof, try-catch blocks, typehints, number of arguments passed to a function, accessibility of called methods and variables, and many more.

Install PHPStan

> composer require --dev phpstan/phpstan


Add helper script commands to composer.json

    "scripts": {

        "phpstan-dev": "php vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G",

        "phpstan-ci": "php vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G --no-progress",

...

    }


-c:
The configuration file phpstan.neon allows you to commit additional options for your project

--memory-limit=1G:
argument is to suppress a common false warning on runs which suggests that the errors are due to a memory limit;  projects often only consume tens to a couple hundreds of MB.

--no-progress:
omits the progress bar which could be useful for Continuous Integration runs.

Configuration

PHPStan makes use of the neon file format for its configuration, which is yaml like. 

An example configuration file, phpstan.neon:

# https://phpstan.org/config-reference

parameters:

    # https://phpstan.org/user-guide/rule-levels

    level: 8

    # code paths

    paths:

        - cfg

        - public

        - src

    excludePaths:

        analyse:

            - vendor

    tmpDir: tmp

    # https://phpstan.org/config-reference#vague-typehints

    checkMissingIterableValueType: false

    checkGenericClassInNonGenericObjectType: false

    # btr if true, but false allows changing level w/o errors

    reportUnmatchedIgnoredErrors: true

    ignoreErrors:

        - '#Negated boolean expression is always true\.#'

        - '#If condition is always false\.#'
...


level:
indicates how many tests to run
https://phpstan.org/user-guide/rule-levels

paths: 

should point to your code


excludePaths:

should exclude code you are not responsible for, such as vendor


tmpDir: 

if not set will use your default os tmp dir, but setting to a local tmp allows for easier cleanup, observation


ignoreErrors:

allows common code patterns in your project to be ignored by PHPStan

https://phpstan.org/user-guide/ignoring-errors

This should be used minimally, but may be necessary depending on your code.  It can also be used when adding PHPStan to an existing project with lots of errors and you want to ease PHPStan into your workflow.


reportUnmatchedIgnoredErrors:

shows you if you have any unused ignoreError expressions


Run PHPStan

Run using composer

> php composer phpstan-dev

php vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G

...

------------------------------------------------------------------------------

  Line   src\Your\Service\AService.php

------------------------------------------------------------------------------

  15     Property App\Your\Service\AService::$aDomain has no typehint specified.

------------------------------------------------------------------------------

...

 [ERROR] Found 214 errors

 115/115 [============================] 100%

Script php vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G handling the phpstan event returned with error code 1


Now the 'fun' begins.  The errors list the file name, method, and line number.  Go through all the reported errors and 'fix' them increasing code quality, and sometimes functionality; and only if necessary, add the error(s) to the ignore list.

Work toward the goal of no reported errors


> php composer phpstan-dev

php vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G


 115/115 [============================] 100%


 [OK] No errors


Now celebrate!

And before every Push, Pull/Merge Request, run PHPStan.

Sounds like a good job for git hooks or CI huh?




-End of Document-

Thanks for reading


Monday, February 21, 2022

Enable PHP 8 xdebug from the command line

 "Xdebug is an extension for PHP, and provides a range of features to improve the PHP development experience. Step Debugging A way to step through your code in your IDE or editor while the script is executing."

Source: https://xdebug.org/ 

Install following the instructions from https://xdebug.org/docs/install

Note, PHP 8 settings are different than earlier versions of PHP, xdebug
For PHP 7 settings, see the prior post 
Enable PHP xdebug from the command line 

Download and place the xdebug extension in php\ext
C:\laragon8\bin\php\php-8.0.11-Win32-vs16-x64\ext

Configure your PHP 8 php.ini settings:

zend_extension=xdebug-3.0.4-8.0-vs16-x86_64

[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9081
xdebug.idekey=PHPSTORM 

Note, if you use xdebug.start_with_request=trigger, this may be more efficient for large code paths as xdebug should only be started when you send a request with XDEBUG_SESSION set, which can be set via xdebug helper for chrome or xdebug helper for firefox


You can also add arguments to your PHP call

> php -d -dxdebug.mode=debug -dxdebug.start_with_request=yes -dxdebug.client_host=127.0.0.1 -dxdebug.client_port=9081 -dxdebug.idekey=PHPSTORM your/script.php

The option -d can set/override php.ini values

-d foo[=bar]     Define INI entry foo with value 'bar'
Reference: https://www.php.net/manual/en/features.commandline.options.php


If you are using the conemu console you can add the alias to your settings -> startup -> environment

alias xphp8=C:/laragon80/bin/php/php-8.0.11-Win32-vs16-x64/php -dxdebug.mode=debug -dxdebug.start_with_request=yes -dxdebug.client_host=127.0.0.1 -dxdebug.client_port=9081 -dxdebug.idekey=PHPSTORM $*

alias php8=C:/laragon80/bin/php/php-8.0.11-Win32-vs16-x64/php $*

If you are using git for windows, which adds bash, you can also add the aliases
Edit your .bashrc
C:\Users\[youruser]\.bashrc

alias xphp8="C:/laragon80/bin/php/php-8.0.11-Win32-vs16-x64/php -dxdebug.mode=debug -dxdebug.start_with_request=yes -dxdebug.client_host=127.0.0.1 -dxdebug.client_port=9081 -dxdebug.idekey=PHPSTORM $*"

alias php8="C:/laragon80/bin/php/php-8.0.11-Win32-vs16-x64/php $*"


And use as

> xphp8 slimapp/cli.php arg1 arg2=test

Reference: Slim PHP CLI

 

-End of Document-
Thanks for reading