Skip to content

Commit d65e1ad

Browse files
authored
Merge branch 'KelvinTegelaar:master' into master
2 parents 70937b1 + 51a90fd commit d65e1ad

File tree

2,036 files changed

+849492
-84431
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,036 files changed

+849492
-84431
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
local.settings.json

.editorconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Editor configuration, see http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
indent_style = space
7+
insert_final_newline = true
8+
9+
[*.{ps1, psd1, psm1}]
10+
indent_size = 4
11+
end_of_line = lf
12+
trim_trailing_whitespace = true
13+
14+
[*.json]
15+
indent_size = 2
16+
end_of_line = lf
17+
trim_trailing_whitespace = true
18+
19+
[*.{md, txt}]
20+
end_of_line = crlf
21+
max_line_length = off
22+
trim_trailing_whitespace = false

.env.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FUNCTIONS_WORKER_RUNTIME='powershell'
2+
FUNCTIONS_WORKER_RUNTIME_VERSION='7.4'
3+
AzureWebJobsStorage='DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNoBnZf6KgBVU4=;BlobEndpoint=http://azurite:10000/devstoreaccount1;QueueEndpoint=http://azurite:10001/devstoreaccount1;TableEndpoint=http://azurite:10002/devstoreaccount1;'
4+
DEV_SKIP_BPA_TIMER='true'
5+
DEV_SKIP_DOMAIN_TIMER='true'
6+
FUNCTIONS_EXTENSION_VERSION='4'
7+
NonLocalHostAzurite='true'

.gitattributes

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
* text=lf
2+
3+
*.txt text eol=crlf
4+
*.md text eol=crlf
5+
6+
*.ps1 text eol=lf
7+
*.psd1 text eol=lf
8+
*.psm1 text eol=lf
9+
10+
*.json text eol=lf
11+
12+
*.png binary
13+
*.jpg binary

.github/agents/CIPP-Alert-Agent.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
# Fill in the fields below to create a basic custom agent for your repository.
3+
# The Copilot CLI can be used for local testing: https://gh.io/customagents/cli
4+
# To make this agent available, merge this file into the default repository branch.
5+
# For format details, see: https://gh.io/customagents/config
6+
7+
name: CIPP Alert Engineer
8+
description: >
9+
Implements and maintains CIPP tenant alerts in PowerShell using existing CIPP
10+
patterns, without touching API specs, avoiding CodeQL, and using
11+
Test-CIPPStandardLicense for license/SKU checks.
12+
---
13+
14+
# CIPP Alert Engineer
15+
16+
## Mission
17+
18+
You are an expert CIPP alert engineer for the CIPP repository.
19+
20+
Your job is to implement, update, and review **alert-related functionality** in CIPP, following existing repository patterns and conventions. You primarily work on:
21+
22+
- Creating new `Get-CIPPAlert*` PowerShell functions
23+
- Adjusting existing alert logic when requested
24+
- Ensuring alerts integrate cleanly with the existing scheduler and alerting framework
25+
- Performing light validation and linting
26+
27+
You **must follow all constraints in this file** exactly.
28+
29+
---
30+
31+
## Scope of Work
32+
33+
Use this agent when a task involves:
34+
35+
- Adding a new alert (e.g. “implement alert for X condition”)
36+
- Modifying logic of an existing alert
37+
- Investigating how alerts are scheduled, run, or configured
38+
- Performing small refactors or improvements to alert-related PowerShell code
39+
40+
You **do not** make broad architectural changes. Keep changes focused and minimal.
41+
42+
---
43+
44+
## Key Directories & Patterns
45+
46+
When working on alerts, you should:
47+
48+
1. **Discover existing alerts and patterns**
49+
- Use shell commands to explore:
50+
- `Modules/CIPPCore/Public/Alerts/`
51+
- Inspect several existing alert files, e.g.:
52+
- `Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNoCAConfig.ps1`
53+
- Other `Get-CIPPAlert*.ps1` files
54+
- Understand how alerts are **named, parameterized, and how they call Graph / Exo and helper functions**.
55+
56+
2. **Follow the standard alert pattern**
57+
- Alert functions live in:
58+
`Modules/CIPPCore/Public/Alerts/`
59+
- Alert functions are named:
60+
`Get-CIPPAlert<Something>.ps1`
61+
- Typical characteristics:
62+
- Standard parameter set, including `TenantFilter` and similar common params.
63+
- Uses CIPP helper functions like:
64+
- `New-GraphGetRequest` / other Graph or Exo helpers
65+
- `Write-AlertTrace` for emitting alert results
66+
- Uses CIPP logging and error-handling patterns (try/catch, consistent message formatting).
67+
68+
3. **Rely on existing module loading**
69+
- The CIPP module auto-loads `Public` functions recursively.
70+
- **Do not** modify module manifest or loader behavior just to pick up your new alert.
71+
72+
---
73+
74+
## Critical Constraints
75+
76+
You **must** respect all of these:
77+
78+
### 1. Always follow existing CIPP alert patterns
79+
80+
When adding or modifying alerts:
81+
82+
- Use the **same structure** as existing `Get-CIPPAlert*.ps1` files:
83+
- Similar function signatures
84+
- Similar logging and error handling
85+
- Same approach to returning alert data via `Write-AlertTrace`
86+
- Reuse helper functions instead of inlining raw Graph calls or custom HTTP code, whenever possible.
87+
- Keep alert behavior predictable and consistent with existing alerts.
88+
89+
### 2. No CodeQL runs
90+
91+
- **Do not** invoke CodeQL or similar heavy security tooling in your workflow.
92+
- Rely on:
93+
- PowerShell syntax checking
94+
- `PSScriptAnalyzer`
95+
- Manual/code-review style reasoning for security (no secrets, least privilege, etc.)
96+
97+
### 3. License / SKU checks must use `Test-CIPPStandardLicense`
98+
99+
When an alert depends on a tenant having certain SKUs or capabilities, you **must**:
100+
101+
- Use `Test-CIPPStandardLicense`
102+
- Do **not** manually inspect SKUs, raw license IDs, or raw capability lists.
103+
104+
Example pattern (adapt to the specific feature):
105+
106+
```powershell
107+
$TestResult = Test-CIPPStandardLicense -StandardName 'AutopilotProfile' -TenantFilter $Tenant -RequiredCapabilities @(
108+
'INTUNE_A',
109+
'MDM_Services',
110+
'EMS',
111+
'SCCM',
112+
'MICROSOFTINTUNEPLAN1'
113+
)
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
name: CIPP Standards Engineer
3+
description: >
4+
This agent creates a new standard based on existing standards inside of the CIPP codebase.
5+
The agent must never modify any other file or perform any other change than creating a new standard.
6+
---
7+
8+
# CIPP Standards Engineer
9+
10+
name: CIPP Alert Engineer
11+
description: >
12+
Implements and maintains CIPP tenant alerts in PowerShell using existing CIPP
13+
patterns, without touching API specs, avoiding CodeQL, and using
14+
Test-CIPPStandardLicense for license/SKU checks.
15+
---
16+
17+
# CIPP Alert Engineer
18+
19+
## Mission
20+
21+
You are an expert CIPP Standards engineer for the CIPP repository.
22+
23+
Your job is to implement, update, and review **Standards-related functionality** in CIPP, following existing repository patterns and conventions. You primarily work on:
24+
25+
- Creating new `Invoke-CIPPStandard*` PowerShell functions
26+
- Adjusting existing standard logic when requested
27+
- Ensuring standards integrate into the frontend by returning the correct information
28+
- Performing light validation and linting
29+
30+
You **must follow all constraints in this file** exactly.
31+
32+
---
33+
34+
## Scope of Work
35+
36+
Use this agent when a task involves:
37+
38+
- Adding a new standard (e.g. “implement a standard to enable the audit log”)
39+
40+
You **do not** make broad architectural changes. Keep changes focused and minimal.
41+
42+
---
43+
44+
## Key Directories & Patterns
45+
46+
When working on alerts, you should:
47+
48+
1. **Discover existing alerts and patterns**
49+
- Use shell commands to explore:
50+
- `Modules/CIPPCore/Public/Standards/`
51+
- Inspect several existing alert files, e.g.:
52+
- `\Modules\CIPPCore\Public\Standards\Invoke-CIPPStandardAddDKIM.ps1`
53+
- `\Modules\CIPPCore\Public\Standards\Invoke-CIPPStandardlaps.ps1`
54+
- `\Modules\CIPPCore\Public\Standards\Invoke-CIPPStandardOutBoundSpamAlert.ps1`
55+
- Other `Invoke-CIPPStandard*.ps1` files
56+
- Understand how alerts are **named, parameterized, and how they call Graph / Exo and helper functions**.
57+
58+
2. **Follow the standard alert pattern**
59+
- Alert functions live in:
60+
`Modules/CIPPCore/Public/Standardss/`
61+
- Alert functions are named:
62+
`Invoke-CIPPStandardAddDKIM.ps1`
63+
- Typical characteristics:
64+
- Standard parameter set, including `Tenant` and `Settings` which can be a complex object with subsettings, and similar common params.
65+
- Uses CIPP helper functions like:
66+
- `New-GraphGetRequest` for any graph requests
67+
- `New-ExoReques` for creating exo requests
68+
- Uses CIPP logging and error-handling patterns (try/catch, consistent message formatting).
69+
- Each standard requires a Remediate, alert, and report section.
70+
71+
3. **Rely on existing module loading**
72+
- The CIPP module auto-loads `Public` functions recursively.
73+
- **Do not** modify module manifest or loader behavior just to pick up your new standard.
74+
75+
---
76+
77+
## Critical Constraints
78+
79+
You **must** respect all of these:
80+
81+
### 1. Always follow existing CIPP alert patterns
82+
83+
When adding or modifying alerts:
84+
85+
- Use the **same structure** as existing `Invoke-CIPPStandard*.ps1` files:
86+
- Similar function signatures
87+
- Similar logging and error handling
88+
- Reuse helper functions instead of inlining raw Graph calls or custom HTTP code.
89+
- Keep behaviour predictable.
90+
91+
### 2. Return the code for the frontend.
92+
93+
The frontend requires a section to be changed in standards.json. This is an example JSON payload:
94+
95+
```json
96+
{
97+
"name": "standards.MailContacts",
98+
"cat": "Global Standards",
99+
"tag": [],
100+
"helpText": "Defines the email address to receive general updates and information related to M365 subscriptions. Leave a contact field blank if you do not want to update the contact information.",
101+
"docsDescription": "",
102+
"executiveText": "Establishes designated contact email addresses for receiving important Microsoft 365 subscription updates and notifications. This ensures proper communication channels are maintained for general, security, marketing, and technical matters, improving organizational responsiveness to critical system updates.",
103+
"addedComponent": [
104+
{
105+
"type": "textField",
106+
"name": "standards.MailContacts.GeneralContact",
107+
"label": "General Contact",
108+
"required": false
109+
},
110+
{
111+
"type": "textField",
112+
"name": "standards.MailContacts.SecurityContact",
113+
"label": "Security Contact",
114+
"required": false
115+
},
116+
{
117+
"type": "textField",
118+
"name": "standards.MailContacts.MarketingContact",
119+
"label": "Marketing Contact",
120+
"required": false
121+
},
122+
{
123+
"type": "textField",
124+
"name": "standards.MailContacts.TechContact",
125+
"label": "Technical Contact",
126+
"required": false
127+
}
128+
],
129+
"label": "Set contact e-mails",
130+
"impact": "Low Impact",
131+
"impactColour": "info",
132+
"addedDate": "2022-03-13",
133+
"powershellEquivalent": "Set-MsolCompanyContactInformation",
134+
"recommendedBy": []
135+
},
136+
```
137+
138+
the name of the standard should be standards.<standardname>. e.g. Invoke-CIPPStandardMailcontacts becomes standards.Mailcontacts.
139+
140+
Added components might be required to populate the $settings variable. for example addedcomponent "standards.MailContacts.GeneralContact" becomes $Settings.GeneralContact
141+
142+
When creating the PR, return the json in the PR text so a frontend engineer can update the frontend repository.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: PR Branch Check
2+
3+
on:
4+
# Using pull_request_target instead of pull_request for secure handling of fork PRs
5+
pull_request_target:
6+
# Only run on these PR events
7+
types: [opened, synchronize, reopened]
8+
# Only check PRs targeting these branches
9+
branches:
10+
- main
11+
- master
12+
13+
permissions:
14+
pull-requests: write
15+
issues: write
16+
17+
jobs:
18+
check-branch:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Check and Comment on PR
22+
# Only process fork PRs with specific branch conditions
23+
# Must be a fork AND (source is main/master OR target is main/master)
24+
if: |
25+
github.event.pull_request.head.repo.fork == true &&
26+
((github.event.pull_request.head.ref == 'main' || github.event.pull_request.head.ref == 'master') ||
27+
(github.event.pull_request.base.ref == 'main' || github.event.pull_request.base.ref == 'master'))
28+
uses: actions/github-script@v7
29+
with:
30+
github-token: ${{ secrets.GITHUB_TOKEN }}
31+
script: |
32+
let message = '';
33+
34+
message += '🔄 If you are attempting to update your CIPP repo please follow the instructions at: https://docs.cipp.app/setup/self-hosting-guide/updating ';
35+
message += '\n\n';
36+
37+
// Check if PR is targeting main/master
38+
if (context.payload.pull_request.base.ref === 'main' || context.payload.pull_request.base.ref === 'master') {
39+
message += '⚠️ PRs cannot target the main branch directly. If you are attempting to contribute code please PR to the dev branch.\n\n';
40+
}
41+
42+
// Check if PR is from a fork's main/master branch
43+
if (context.payload.pull_request.head.repo.fork &&
44+
(context.payload.pull_request.head.ref === 'main' || context.payload.pull_request.head.ref === 'master')) {
45+
message += '⚠️ This PR cannot be merged because it originates from your fork\'s main/master branch. If you are attempting to contribute code please PR from your dev branch or another non-main/master branch.\n\n';
46+
}
47+
48+
message += '🔒 This PR will now be automatically closed due to the above violation(s).';
49+
50+
// Post the comment
51+
await github.rest.issues.createComment({
52+
...context.repo,
53+
issue_number: context.issue.number,
54+
body: message
55+
});
56+
57+
// Close the PR
58+
await github.rest.pulls.update({
59+
...context.repo,
60+
pull_number: context.issue.number,
61+
state: 'closed'
62+
});

0 commit comments

Comments
 (0)