Category Archives: 06 – Security & Access

Access Control

Welcome to the NZRT Wiki Podcast. Today we’re looking at 🔐 Access Control.

If you work with the NZRT GitHub organisation, understanding who can do what is essential. GitHub access control comes down to two core ideas: roles and teams. Roles define what a person or group can actually do inside a repository, and teams are groups of users who share those permissions together.

Let me walk you through the five roles NZRT uses, from most powerful to least. At the top you have Admin — that is full access, including deleting repositories and changing settings. Below that is Maintain, which lets you push code, merge pull requests, create releases, and adjust certain settings. Then there is Write, giving you the ability to push commits and create branches. Triage is more limited — it is for managing issues and pull request labels, but you cannot push code. And finally, Pull is read-only: you can clone and view, but nothing more.

Now, how does NZRT map these roles to people? The wiki has a table, so let me walk you through each row. There are five entries. First, xc holds the Admin role — full access across all repositories, sitting in the Admin team. Second, pam, fin, and dan all have the Maintain role, in the Team Leads group, each assigned to their relevant repositories. Third, developers get Write access across all repos. Fourth, cas has Triage access through the Sales team — read-only on code, but able to manage issues and labels. And fifth, dai has Pull access through the Data team, meaning read-only across everything.

The wiki also shows the full organisation structure as a visual tree. Think of it this way. At the top is the NZRT GitHub organisation. Underneath that you have two branches — Teams and Repositories. On the Teams side there are five groups. The Admin team, which is xc, has Admin permissions everywhere. The Product Managers team, which is pam, has Maintain access specifically to the nzrt-scripts repository. The Finance team, which is fin, has Maintain access to the dolibarr-custom repository. The Data team, which is dai, has Pull — read-only — access across all repositories. And the Developers team has Write access to everything. On the Repositories side, there are two private repos listed: dolibarr-custom and nzrt-scripts.

So how do you actually assign access? There are two methods. The first is adding a team to a repository. You go into repository settings, find Collaborators and Teams, click Add Teams, select the team you want such as Product Managers or Finance, set the role, and confirm. The second method is adding an individual user directly. Same starting point — repository settings, Collaborators and Teams — but this time you click Add People, search by GitHub username, set the role, and confirm.

Now let me explain the CODEOWNERS file, which is a really useful automation tool. You create this file inside the dot-github folder of your repository. It maps file paths to teams or people who are automatically requested as reviewers whenever a pull request touches those files. The wiki shows several examples, so let me explain what each one does in plain terms. There is a catch-all pattern that makes the admin team a global reviewer of everything. Then, any changes inside the WordPress plugin folder — specifically the wp-sync-core plugin path — will automatically request the Product Managers team for review. Changes to the ERP customisation module request both Product Managers and Finance. Anything touching dolibarr integration modules routes to Finance only. Changes to the CI/CD workflow files go to the Admin team. And any database scripts in the SQL folder are routed to a DBA team. The core idea is simple: when a pull request touches a specific path, the matching team or person is automatically pulled in to review — no manual assignment needed.

That is it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Branch Protection

Welcome to the NZRT Wiki Podcast. Today we’re looking at ??? Branch Protection.

If you’ve ever pushed a change directly to your main branch and immediately regretted it, branch protection is the feature that’s going to save you from yourself. At NZRT, branch protection rules are applied to two critical branches across our repositories — main, which is production, and develop, which is staging. Let’s walk through what that actually means and why it matters.

The idea behind branch protection is straightforward. You’re preventing accidental or unauthorized changes from landing in places that really count. GitHub gives you a toolkit of rules you can switch on, and NZRT uses most of them. Let’s run through the key ones so you know what you’re working with.

First up, requiring pull request reviews. This means nobody can merge code into a protected branch without it going through a pull request and getting approved. Alongside that, there’s a dismiss stale reviews setting, which means if someone approves your pull request and you then push more commits, that approval gets wiped out. You need a fresh sign-off on what’s actually in the branch right now.

Then there’s requiring code owner review. NZRT uses code owner files to automatically assign the right people to review changes in specific parts of the codebase. If this rule is on, those assigned owners have to approve before anything merges.

Require status checks is another important one. This means your GitHub Actions workflows — things like build jobs, linting, security scans, and tests — all have to pass before the merge button becomes available. Combined with the require branches up to date rule, your branch also has to be current with the base branch before you can merge. There’s also the option to require signed commits, restrict who can push, and auto-delete head branches after a merge to keep things tidy.

Now let’s look at how NZRT actually configures these for a real repository. Taking the Dolibarr Custom repository as an example — for the main branch, which is production, the settings require two approvals before any pull request can merge. Stale reviews are dismissed, code owner review is required, and three status checks must pass: the build job, PHP linting, and a security scan. The branch must be up to date before merging. Only admins can push directly, and only admins can force push. Head branches are automatically deleted after merge.

For the develop branch on that same repository, the rules are a bit more relaxed. You only need one approval instead of two. Stale reviews are still dismissed, but code owner review is not required. All GitHub Actions must still pass and the branch must be up to date, but developers can push small fixes directly without needing admin rights. Auto-delete is still on.

A second repository configuration follows a similar pattern for its main branch — one approval required, stale reviews dismissed, code owner review on. It requires four status checks to pass: PHP linting, PHPStan static analysis, unit tests, and integration tests. Push access is restricted to admins, and head branches auto-delete on merge.

If you need to set up branch protection on a repository yourself, the process is simple. You go to repository settings, find the branches section, and click add rule. You enter the branch name pattern — so that would be something like main, develop, or a wildcard covering all release branches. Then you tick the boxes for the rules you want to apply and save.

Now, what happens if there’s an emergency and you genuinely need to bypass protection? NZRT has a defined hotfix process for exactly that. You create a hotfix branch directly from main, make your critical fix, then request a review from someone with admin rights — that’s the xc role at NZRT. You create a pull request, get at least one approval, and merge using a merge commit so the history is preserved. Then you deploy to production immediately, cherry-pick the fix across to develop, and follow up with a post-incident review.

If a full admin override is truly needed and someone with the xc role needs to push directly to main, they must log the reason in a GitHub issue, create a pull request afterward for the audit trail, and notify the team straight away.

Branch protection is one of those things that feels like overhead until the day it stops a bad deploy from happening. Getting it right across your repositories means your production code stays trustworthy and your team has a clear, consistent process to follow every time.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Secrets Tokens

Welcome to the NZRT Wiki Podcast. Today we’re looking at Secrets and Tokens.

If you’ve spent any time working with GitHub Actions at NZRT, you’ve probably heard the term secrets thrown around. So let’s break down what they actually are, how NZRT uses them, and what you need to know to keep things secure.

At the most basic level, GitHub Secrets are encrypted environment variables. Think of them as a secure vault that GitHub Actions can reach into during a workflow run. Once a secret is stored, you can never read it back out through the GitHub interface — it’s write-only. The only time it appears is when a workflow actively uses it, and even then, GitHub automatically masks the value in your logs, replacing it with three asterisks so nothing sensitive ever gets printed.

Now, secrets come in three flavours. Repository secrets are encrypted and tied to a single repository. Organization secrets sit at the org level and can be shared across multiple repos. And environment secrets are scoped to specific deployment environments, like staging or production. This gives you a layered system where sensitive values live exactly where they need to be and nowhere else.

Here’s what NZRT currently has set up at the repository level. There are six secrets in use. The first two are SSH private keys — one called STAGING DEPLOY KEY for the staging server, and PROD DEPLOY KEY for production. Both are used by the deploy workflow. Then there’s the DOLIBARR API KEY, which sync workflows use to talk to the Dolibarr REST API. There’s a SLACK WEBHOOK secret for sending notifications from within jobs. A CODECOV TOKEN for coverage reporting during test runs. And finally, GITHUB TOKEN, which GitHub generates automatically and is available to all workflows.

At the organization level, NZRT shares two secrets across multiple repos. PROD DEPLOY KEY covers both the dolibarr-custom and nzrt-scripts repositories. And GITHUB TOKEN is available to everything in the org.

So how do you actually use a secret inside a workflow? The example in the wiki shows a deployment job where secrets are mapped to environment variables within a step. The deploy key and the API key are pulled in by name, and the shell script then references those environment variables. You’re never hard-coding the actual values — the workflow just knows to look for them by name and GitHub injects them at runtime. If you accidentally tried to print one of these values, GitHub would replace it with asterisks automatically. But the best practice is to simply not log secrets at all, even though masking protects you.

Let’s talk about how you create these secrets in the first place. For a GitHub personal access token, you go into your account settings, then Developer Settings, then Personal Access Tokens. You generate a new classic token, select the scopes you need — typically repo, admin repo hook, workflow, and read org — then copy the token and store it in your repository secrets.

For SSH deployment keys, the process is a two-step command-line workflow. First, you generate a new RSA key pair at 4096 bits with no passphrase — the no passphrase part matters because automation can’t type a password interactively. Then you take the private key, encode it in base64, and store that encoded value in GitHub Secrets. The matching public key goes onto the production server’s list of authorized keys. That way, GitHub Actions can authenticate over SSH without the actual private key ever appearing in a script.

NZRT also follows a naming convention for custom tokens. The pattern is a prefix, then the environment, then the type — so for example NZRT STAGING DEPLOY KEY or NZRT PROD DEPLOY KEY. This makes it immediately clear what each secret does and where it belongs.

Now, secrets don’t last forever — and they shouldn’t. The wiki includes a rotation checklist you should keep in mind. SSH deploy keys should be rotated every six months. API tokens every three months. Database passwords quarterly. You should also regularly review secret access in the GitHub audit log, remove secrets tied to anyone who leaves the team, and revoke anything that gets accidentally exposed the moment you discover it. That last point is non-negotiable — treat a leaked secret as fully compromised from the instant you find out.

One final thing worth remembering: secrets are only accessible during a workflow run. They’re never embedded in your code, never visible in the repository, and never returned through the GitHub API once stored. That’s the whole point — they stay in the vault until Actions needs them, and then they’re gone again.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Security Best Practices

Welcome to the NZRT Wiki Podcast. Today we’re looking at Security Best Practices.

Security is everyone’s responsibility at NZRT, and today we’re walking through the core principles and practices that protect our code, credentials, and data — whether you’re a developer, a team lead, or just getting started.

Let’s start with the big ideas. At NZRT, security thinking is built around a handful of key concepts. First is the principle of least privilege — you only get the access you actually need to do your job, nothing more. Next is defense in depth, which means we don’t rely on just one security measure. We layer authentication, encryption, and logging so that if one control fails, others are still protecting you. Then there’s secret hygiene — never commit secrets to code, and rotate them regularly. We also insist on code review, audit trails, supply chain security for your dependencies and third-party code, and a clear incident response plan so you can act quickly when something goes wrong.

Now let’s talk about what that looks like day to day. NZRT has a security checklist covering five areas: repository setup, credentials and secrets, access control, code quality, and deployment.

Starting with your repository. Every repo should be private, with branch protection turned on for the main and develop branches. You need a CODEOWNERS file, a README with security instructions, and a gitignore that excludes things like dot-env files, secrets folders, and key files. And critically — no sensitive data should ever appear in your commit history.

On credentials and secrets: no API keys, tokens, or passwords go in the code. Full stop. Secrets live in GitHub Secrets, not in files. Database credentials go in a dot-env file, not in the example version that gets committed. You rotate credentials every three months, and you watch the audit log for unusual access.

For access control, team members get only the roles they need. Inactive users get removed. Admin access is limited to essential people. Two-factor authentication is on every account, SSH keys are registered and verified on GitHub, and personal access tokens are scoped as narrowly as possible.

On code quality: GitHub Actions runs on every pull request — linting, tests, and security scanning. You’re targeting test coverage above eighty percent. No hardcoded credentials. Dependencies are checked for vulnerabilities using Dependabot.

And for deployment: production uses SSH keys, not passwords. Deployments only go through GitHub Actions so they’re reproducible and audited. Status checks must pass before any merge, deployments are logged with timestamps and version numbers, and your rollback procedure is documented and tested.

Now for the secret management policy. NZRT tracks five categories of secrets. Think of it as a table with four columns — the type, some examples, how often you rotate, and where they’re stored. Database passwords like your MySQL credentials rotate quarterly and live in GitHub Secrets. API tokens — things like your Dolibarr or Slack tokens — also rotate quarterly and also go in GitHub Secrets. SSH deploy keys rotate every six months, again in GitHub Secrets. OAuth tokens like your GitHub token rotate quarterly. And SSL certificate private keys rotate annually and live in the server keystore.

What if a credential gets leaked? There’s a clear six-step response. First, immediately disable that credential at the source system. Second, use a tool called BFG Repo-Cleaner to scrub every occurrence from git history. Third, force-push the cleaned history. Fourth, rotate all related credentials — not just the one that leaked. Fifth, log the incident and write a postmortem. Sixth, notify any affected services.

Code review is your last line of defence before code ships. When you review a pull request, you’re checking that there are no secrets or hardcoded paths, that user input is validated, that output is properly escaped to prevent cross-site scripting, that database queries use parameterized statements, that authentication and authorization checks are in place, and that error messages don’t accidentally expose sensitive information.

And if a security issue is detected, follow seven steps: isolate the affected service or roll back the deployment, assess the scope and impact, notify the admin and relevant team leads, remediate and deploy a patch, verify the fix is working, document everything in a postmortem, and if user data was affected, communicate that to the right people.

Security isn’t a one-time setup — it’s an ongoing practice. Keep your credentials rotated, your reviews thorough, and your incident response sharp.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.