mirror of
https://github.com/kerberos-io/helm-charts.git
synced 2026-11-12 21:30:24 +00:00
Compare commits
89
Commits
@@ -0,0 +1,28 @@
|
||||
name: HTTP port migration
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
migration:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: azure/setup-helm@v4.3.1
|
||||
- uses: helm/kind-action@v1
|
||||
- name: Validate migration against Kubernetes
|
||||
env:
|
||||
SERVER_VALIDATION: "true"
|
||||
run: bash scripts/check-http-port-migration.sh
|
||||
- name: Validate chart runtime compatibility
|
||||
run: |
|
||||
helm lint charts/hub
|
||||
bash scripts/check-admin-runtime.sh
|
||||
bash scripts/check-hardened-workers.sh
|
||||
bash scripts/check-frontend-runtime.sh
|
||||
bash scripts/check-hub-api-runtime.sh
|
||||
- name: Smoke test hardened frontend images and Service routing
|
||||
env:
|
||||
CLUSTER_SMOKE: "true"
|
||||
run: bash scripts/check-frontend-runtime.sh
|
||||
@@ -16,7 +16,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.159.0
|
||||
version: 0.186.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
||||
+858
-56
File diff suppressed because it is too large
Load Diff
@@ -2,15 +2,15 @@ Kerberos.io
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Activate your account ->
|
||||
|
||||
One of your Kerberos Agents changed
|
||||
{{text}}
|
||||
|
||||
Agents go offline due to a variety of reasons. The machine, node, micro controller on which your Agent runs, gets corrupted or disconnected from the internet. The camera itself is broken, damaged or in the worst case tampered. Have a look into your Kerberos Hub account for the latest recordings and/or verify the connection and status of your Kerberos Agent.
|
||||
|
||||
Go to Kerberos Hub ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
Get in touch
|
||||
------------
|
||||
support@kerberos.io
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-Regular.woff?v=/dist/fonts/Inter-Regular.woff2?v=3.183.18") format("woff2"),
|
||||
url("https://kerberos.io/dist/fonts/Inter-Regular.woff?v=/dist/fonts/Inter-Regular.woff2?v=3.183.18") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-Medium.woff2?v=3.18") format("woff2"),
|
||||
url("https://kerberos.io/dist/fonts/Inter-Medium.woff?v=3.18") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-SemiBold.woff2?v=3.18") format("woff2"),
|
||||
url("https://kerberos.io/dist/fonts/Inter-SemiBold.woff?v=3.18") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter var';
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
font-style: normal;
|
||||
font-named-instance: 'Regular';
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-roman.var.woff2?v=3.18") format("woff2");
|
||||
}
|
||||
|
||||
body{
|
||||
background: #E5E5E5;
|
||||
margin-top:0;
|
||||
margin-bottom: 0;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
padding-top: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-bottom: 0;
|
||||
font-family: 'Inter';
|
||||
}
|
||||
a, a:hover, a:active {
|
||||
color: #262424;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.corner-td{
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
table {border-collapse:separate;max-width: 850px; margin: 0 auto; width: 100%;}
|
||||
.ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td {line-height: 100%;}
|
||||
.ExternalClass {width: 100%;}
|
||||
@media screen and (max-width:500px){
|
||||
.tab-td{
|
||||
padding-left: 10px!important;
|
||||
}
|
||||
.tab-td a h4{
|
||||
font-size: 14px!important;
|
||||
}
|
||||
.corner-td{
|
||||
width: 20px!important;
|
||||
}
|
||||
.company-name-td h3{
|
||||
font-size: 16px!important;
|
||||
}
|
||||
table.header-table{
|
||||
padding-top: 8px!important;
|
||||
padding-right: 0px!important;
|
||||
padding-bottom: 24px!important;
|
||||
padding-left: 0px!important;
|
||||
}
|
||||
.colored-card-td h4{
|
||||
font-size: 14px!important;
|
||||
}
|
||||
.colored-card-td h2{
|
||||
font-size: 20px!important;
|
||||
}
|
||||
.colored-card-td a p{
|
||||
font-size: 12px!important;
|
||||
width: 143px!important;
|
||||
}
|
||||
.colored-card-td{
|
||||
padding-top: 24px!important;
|
||||
padding-right: 24px!important;
|
||||
padding-bottom: 24px!important;
|
||||
padding-left: 24px!important;
|
||||
}
|
||||
.colorless-card-td{
|
||||
padding-top: 24px!important;
|
||||
padding-right: 24px!important;
|
||||
padding-bottom: 24px!important;
|
||||
padding-left: 24px!important;
|
||||
}
|
||||
.colorless-card-td h3{
|
||||
font-size: 18px!important;
|
||||
}
|
||||
.colorless-card-td p{
|
||||
font-size: 14px!important;
|
||||
}
|
||||
.colorless-card-table{
|
||||
margin-left: 0px!important;
|
||||
margin-right: 0px!important;
|
||||
margin-top: 24px!important;
|
||||
margin-bottom: 24px!important;
|
||||
}
|
||||
.footer-td{
|
||||
display: table-row!important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width:600px) {
|
||||
.footer-td{
|
||||
display: table-row!important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width:650px) {
|
||||
.footer-table{
|
||||
margin-left: 0px!important;
|
||||
margin-right: 0px!important;
|
||||
margin-top: 0px!important;
|
||||
margin-bottom: 36px!important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body height="100%" width="100%">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" height="36" class="header-table" style="padding-top: 36px ;padding-right: 0;padding-bottom: 36px;padding-left: 0;border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
<h4 style="font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: right;
|
||||
color: #6D6666;">{{tab1_title}}</h4>
|
||||
</a>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right" >
|
||||
<a style="text-decoration: none;color: none;" href={{tab2_href}}>
|
||||
<h4 style="font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: right;
|
||||
color: #6D6666;">{{tab2_title}}</h4>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;" >
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td class="colored-card-td" bgcolor="#57356B" style="padding-left: 48px;padding-right: 48px;padding-top: 48px;padding-bottom: 48px;border-radius: 4px;background-color:#57356B;">
|
||||
<h4 style="font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#b09fb9;">Hey, {{user}}</h4>
|
||||
<h2 style=" font-family: Inter;
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#FFFFFF;
|
||||
padding-top: 12px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;">Several of your cameras changed status</h2>
|
||||
<h2 style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#FFFFFF;
|
||||
padding-top: 0;
|
||||
padding-bottom: 24px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
color:#b09fb9;">{{text}}</h2>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="colorless-card-table" style="margin-top: 36px;margin-bottom: 36px;margin-left: 0;margin-right: 0;border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;" >
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td class="colorless-card-td" bgcolor="#FFFFFF" style="background-color:#FFFFFF;padding-top: 36px;padding-right: 43px;padding-bottom: 25px;padding-left: 43px;border-radius: 4px;">
|
||||
<h3 style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;
|
||||
width: 480px">What changed</h3>
|
||||
{{sections}}
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">Cameras that change status together usually share a cause, such as a site losing or regaining its internet connection or power. Have a look into your Kerberos Hub account for the latest recordings and the status of your cameras.</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
<p style="font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#FFFFFF;
|
||||
background-color: #84559F;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
width: 160px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;">Go to Kerberos Hub -></p>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="footer-table" style="margin-top: 0;border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;" >
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;display:table-row !important">
|
||||
<![endif]-->
|
||||
<td height="146" width="190" class="footer-td" style="margin-bottom: 12px;" valign="top" align="left">
|
||||
<table style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<h4 style=" font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">Get in touch</h4>
|
||||
<a style="text-decoration: none;color: none;" href="mailto:support@verstraeten.io">
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">support@kerberos.io</p>
|
||||
</a>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">9000 Ghent, BE</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="https://kerberos.io/">
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">https://kerberos.io</p>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;display:table-row !important">
|
||||
<![endif]-->
|
||||
<td class="footer-td" style="border-radius: 4px;padding-left: 0;padding-right: 0;padding-top: 0;padding-bottom: 0; margin-bottom: 12px;" valign="top" align="left">
|
||||
<table style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<h4 style=" font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.</p>
|
||||
|
||||
|
||||
<p style="margin-top: 12px;">
|
||||
<a href="https://twitter.com/kerberosio" style="text-decoration: none;color: none;">
|
||||
<img width="24" height="24" alt="Twitter" src="https://kerberos.io/images/email/twitter.png"/>
|
||||
</a>
|
||||
<a href="https://reddit.com/r/kerberos_io" style="text-decoration: none;color: none;">
|
||||
<img g width="24" height="24" alt="Reddit" src="https://kerberos.io/images/email/reddit.png"/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/channel/UCnd9q7iRNNw4W95eQwQuECA" style="text-decoration: none;color: none;">
|
||||
<img g width="24" height="24" alt="Youtube" src="https://kerberos.io/images/email/youtube.png"/>
|
||||
</a>
|
||||
<a href="https://github.com/kerberos-io" style="text-decoration: none;color: none;">
|
||||
<img g width="24" height="24" alt="Github" src="https://kerberos.io/images/email/github.png"/>
|
||||
</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr style="height: 50px">
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
Kerberos.io
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
|
||||
Several of your cameras changed status
|
||||
{{text}}
|
||||
|
||||
{{sectionsText}}
|
||||
|
||||
Go to Kerberos Hub ->
|
||||
{{link}}
|
||||
|
||||
Get in touch
|
||||
------------
|
||||
support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
@@ -0,0 +1,431 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-Regular.woff?v=/dist/fonts/Inter-Regular.woff2?v=3.183.18") format("woff2"),
|
||||
url("https://kerberos.io/dist/fonts/Inter-Regular.woff?v=/dist/fonts/Inter-Regular.woff2?v=3.183.18") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-Medium.woff2?v=3.18") format("woff2"),
|
||||
url("https://kerberos.io/dist/fonts/Inter-Medium.woff?v=3.18") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-SemiBold.woff2?v=3.18") format("woff2"),
|
||||
url("https://kerberos.io/dist/fonts/Inter-SemiBold.woff?v=3.18") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter var';
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
font-style: normal;
|
||||
font-named-instance: 'Regular';
|
||||
src: url("https://kerberos.io/dist/fonts/Inter-roman.var.woff2?v=3.18") format("woff2");
|
||||
}
|
||||
|
||||
body{
|
||||
background: #E5E5E5;
|
||||
margin-top:0;
|
||||
margin-bottom: 0;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
padding-top: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-bottom: 0;
|
||||
font-family: 'Inter';
|
||||
}
|
||||
a, a:hover, a:active {
|
||||
color: #262424;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.corner-td{
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
table {border-collapse:separate;max-width: 850px; margin: 0 auto; width: 100%;}
|
||||
.ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td {line-height: 100%;}
|
||||
.ExternalClass {width: 100%;}
|
||||
@media screen and (max-width:500px){
|
||||
.tab-td{
|
||||
padding-left: 10px!important;
|
||||
}
|
||||
.tab-td a h4{
|
||||
font-size: 14px!important;
|
||||
}
|
||||
.corner-td{
|
||||
width: 20px!important;
|
||||
}
|
||||
.company-name-td h3{
|
||||
font-size: 16px!important;
|
||||
}
|
||||
table.header-table{
|
||||
padding-top: 8px!important;
|
||||
padding-right: 0px!important;
|
||||
padding-bottom: 24px!important;
|
||||
padding-left: 0px!important;
|
||||
}
|
||||
.colored-card-td h4{
|
||||
font-size: 14px!important;
|
||||
}
|
||||
.colored-card-td h2{
|
||||
font-size: 20px!important;
|
||||
}
|
||||
.colored-card-td a p{
|
||||
font-size: 12px!important;
|
||||
width: 143px!important;
|
||||
}
|
||||
.colored-card-td{
|
||||
padding-top: 24px!important;
|
||||
padding-right: 24px!important;
|
||||
padding-bottom: 24px!important;
|
||||
padding-left: 24px!important;
|
||||
}
|
||||
.colorless-card-td{
|
||||
padding-top: 24px!important;
|
||||
padding-right: 24px!important;
|
||||
padding-bottom: 24px!important;
|
||||
padding-left: 24px!important;
|
||||
}
|
||||
.colorless-card-td h3{
|
||||
font-size: 18px!important;
|
||||
}
|
||||
.colorless-card-td p{
|
||||
font-size: 14px!important;
|
||||
}
|
||||
.colorless-card-table{
|
||||
margin-left: 0px!important;
|
||||
margin-right: 0px!important;
|
||||
margin-top: 24px!important;
|
||||
margin-bottom: 24px!important;
|
||||
}
|
||||
.footer-td{
|
||||
display: table-row!important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width:600px) {
|
||||
.footer-td{
|
||||
display: table-row!important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width:650px) {
|
||||
.footer-table{
|
||||
margin-left: 0px!important;
|
||||
margin-right: 0px!important;
|
||||
margin-top: 0px!important;
|
||||
margin-bottom: 36px!important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body height="100%" width="100%">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" height="36" class="header-table" style="padding-top: 36px ;padding-right: 0;padding-bottom: 36px;padding-left: 0;border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
<h4 style="font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: right;
|
||||
color: #6D6666;">{{tab1_title}}</h4>
|
||||
</a>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right" >
|
||||
<a style="text-decoration: none;color: none;" href={{tab2_href}}>
|
||||
<h4 style="font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: right;
|
||||
color: #6D6666;">{{tab2_title}}</h4>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;" >
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td class="colored-card-td" bgcolor="#57356B" style="padding-left: 48px;padding-right: 48px;padding-top: 48px;padding-bottom: 48px;border-radius: 4px;background-color:#57356B;">
|
||||
<h4 style="font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#b09fb9;">Hey, {{user}}</h4>
|
||||
<h2 style=" font-family: Inter;
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#FFFFFF;
|
||||
padding-top: 12px;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;">Camera recordings</h2>
|
||||
<h2 style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#FFFFFF;
|
||||
padding-top: 0;
|
||||
padding-bottom: 24px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
color:#b09fb9;">{{text}}</h2>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="colorless-card-table" style="margin-top: 36px;margin-bottom: 36px;margin-left: 0;margin-right: 0;border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;" >
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td class="colorless-card-td" bgcolor="#FFFFFF" style="background-color:#FFFFFF;padding-top: 36px;padding-right: 43px;padding-bottom: 25px;padding-left: 43px;border-radius: 4px;">
|
||||
<h3 style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;
|
||||
width: 480px">Cameras</h3>
|
||||
{{sections}}
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">These cameras record continuously, so a new recording normally arrives every few minutes. When a camera is online but its recordings stop arriving, check that the account has not reached its upload limit, that the storage the recordings are sent to is reachable and not full, and that the Agent's cloud settings and credentials are still valid. Cameras that are recording again need no action.</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
<p style="font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#FFFFFF;
|
||||
background-color: #84559F;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
width: 160px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;">Go to Kerberos Hub -></p>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="E5E5E5" style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tr>
|
||||
<td bgcolor="E5E5E5">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="footer-table" style="margin-top: 0;border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;" >
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;display:table-row !important">
|
||||
<![endif]-->
|
||||
<td height="146" width="190" class="footer-td" style="margin-bottom: 12px;" valign="top" align="left">
|
||||
<table style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<h4 style=" font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">Get in touch</h4>
|
||||
<a style="text-decoration: none;color: none;" href="mailto:support@verstraeten.io">
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">support@kerberos.io</p>
|
||||
</a>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">9000 Ghent, BE</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="https://kerberos.io/">
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">https://kerberos.io</p>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<!--[if mso | IE]>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;display:table-row !important">
|
||||
<![endif]-->
|
||||
<td class="footer-td" style="border-radius: 4px;padding-left: 0;padding-right: 0;padding-top: 0;padding-bottom: 0; margin-bottom: 12px;" valign="top" align="left">
|
||||
<table style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<h4 style=" font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #A69D9D;">Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.</p>
|
||||
|
||||
|
||||
<p style="margin-top: 12px;">
|
||||
<a href="https://twitter.com/kerberosio" style="text-decoration: none;color: none;">
|
||||
<img width="24" height="24" alt="Twitter" src="https://kerberos.io/images/email/twitter.png"/>
|
||||
</a>
|
||||
<a href="https://reddit.com/r/kerberos_io" style="text-decoration: none;color: none;">
|
||||
<img g width="24" height="24" alt="Reddit" src="https://kerberos.io/images/email/reddit.png"/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/channel/UCnd9q7iRNNw4W95eQwQuECA" style="text-decoration: none;color: none;">
|
||||
<img g width="24" height="24" alt="Youtube" src="https://kerberos.io/images/email/youtube.png"/>
|
||||
</a>
|
||||
<a href="https://github.com/kerberos-io" style="text-decoration: none;color: none;">
|
||||
<img g width="24" height="24" alt="Github" src="https://kerberos.io/images/email/github.png"/>
|
||||
</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table style="border-collaps:collaps; mso-table-lspace:0pt; mso-table-rspace:0pt;">
|
||||
<tbody>
|
||||
<tr style="height: 50px">
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
Kerberos.io
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
|
||||
Camera recordings
|
||||
{{text}}
|
||||
|
||||
{{sectionsText}}
|
||||
|
||||
These cameras record continuously, so a new recording normally arrives every few minutes. When a camera is online but its recordings stop arriving, check that the account has not reached its upload limit, that the storage the recordings are sent to is reachable and not full, and that the Agent's cloud settings and credentials are still valid. Cameras that are recording again need no action.
|
||||
|
||||
Go to Kerberos Hub ->
|
||||
{{link}}
|
||||
|
||||
Get in touch
|
||||
------------
|
||||
support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
@@ -1,7 +1,6 @@
|
||||
# Create these ConfigMaps in the release namespace before deploying the chart.
|
||||
# Keys contain complete contracts/catalogs; they are not merged with chart data.
|
||||
# Remove the retired classificationCatalog key from every values overlay.
|
||||
# Do not also set classificationCatalogExistingConfigMap.
|
||||
# Do not also set classificationCatalog or classificationCatalogExistingConfigMap.
|
||||
classificationCatalogEnabled: true
|
||||
workflowConfiguration:
|
||||
enabled: true
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
|
||||
{{/* Normalize both interfaces without changing the caller's values. */}}
|
||||
{{- define "hub.workflowConfiguration.settings" -}}
|
||||
{{- if hasKey .Values "classificationCatalog" -}}
|
||||
{{- fail "classificationCatalog is no longer supported; remove the values key and place the complete catalog in a ConfigMap, then use workflowConfiguration.configMaps with path: catalogs/classifications.json and replace: true" -}}
|
||||
{{- end -}}
|
||||
{{- $config := .Values.workflowConfiguration | default dict -}}
|
||||
{{- $unified := or (hasKey $config "includeDefaults") (hasKey $config "configMaps") -}}
|
||||
{{- $legacy := or (hasKey $config "existingConfigMap") (hasKey $config "items") (hasKey $config "extraConfigMaps") -}}
|
||||
@@ -78,6 +75,17 @@
|
||||
{{- fail "a classifications.json replacement cannot be combined with classificationCatalogExistingConfigMap; choose one override mechanism" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "invalid" .Values.classificationCatalog) -}}
|
||||
{{- if not .Values.classificationCatalogEnabled -}}
|
||||
{{- fail "classificationCatalog requires classificationCatalogEnabled; remove the inline list to use the API fallback" -}}
|
||||
{{- end -}}
|
||||
{{- if .Values.classificationCatalogExistingConfigMap -}}
|
||||
{{- fail "classificationCatalog cannot be combined with classificationCatalogExistingConfigMap; choose one override mechanism" -}}
|
||||
{{- end -}}
|
||||
{{- if hasKey $replacements "catalogs/classifications.json" -}}
|
||||
{{- fail "classificationCatalog cannot be combined with a classifications.json replacement; choose one override mechanism" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- dict "enabled" $enabled "includeDefaults" $includeDefaults "configMaps" $normalizedSources "replacements" $replacements | toYaml -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{{/*
|
||||
The system tag catalog (deviceTags.system.catalog) uses the Hub shared choice
|
||||
catalog format: {key, label, description?}. values.schema.json validates each
|
||||
entry (key in stored device tag form, models.NormalizeDeviceTags: 1-64
|
||||
characters of a-z, 0-9, ".", "_", ":" and "-", starting and ending with a
|
||||
letter or digit) and that enabled is a boolean; keys must also be unique.
|
||||
*/}}
|
||||
{{- define "kerberoshub.deviceTags.system.validate" -}}
|
||||
{{- $seen := dict -}}
|
||||
{{- range $tag := (include "kerberoshub.deviceTags.system.catalog" . | fromJsonArray) -}}
|
||||
{{- $key := toString $tag.key -}}
|
||||
{{- if hasKey $seen $key -}}
|
||||
{{- fail (printf "deviceTags.system.catalog: duplicate key %q" $key) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $seen $key true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
The configured system tag catalog as a JSON array, whether or not system tags
|
||||
are enabled (missing values read as empty).
|
||||
*/}}
|
||||
{{- define "kerberoshub.deviceTags.system.catalog" -}}
|
||||
{{- $deviceTags := .Values.deviceTags | default dict -}}
|
||||
{{- $system := $deviceTags.system | default dict -}}
|
||||
{{- $system.catalog | default list | toJson -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Whether system tags are enabled (deviceTags.system.enabled): "true" or "".
|
||||
*/}}
|
||||
{{- define "kerberoshub.deviceTags.system.enabled" -}}
|
||||
{{- $deviceTags := .Values.deviceTags | default dict -}}
|
||||
{{- $system := $deviceTags.system | default dict -}}
|
||||
{{- if and (kindIs "bool" $system.enabled) $system.enabled -}}true{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
The system tag catalog file hub-api reads (DEVICE_SYSTEM_TAGS_FILE), rendered
|
||||
from deviceTags.system.catalog into the device-system-tags ConfigMap.
|
||||
*/}}
|
||||
{{- define "kerberoshub.deviceTags.system.json" -}}
|
||||
{{- include "kerberoshub.deviceTags.system.validate" . -}}
|
||||
{{- $tags := list -}}
|
||||
{{- range $tag := (include "kerberoshub.deviceTags.system.catalog" . | fromJsonArray) -}}
|
||||
{{- $entry := dict "key" $tag.key "label" $tag.label -}}
|
||||
{{- with $tag.description }}{{- $_ := set $entry "description" . -}}{{- end }}
|
||||
{{- $tags = append $tags $entry -}}
|
||||
{{- end -}}
|
||||
{{- $tags | toJson -}}
|
||||
{{- end -}}
|
||||
@@ -84,17 +84,88 @@ Usage: {{- include "hub.mongodb.appUriEnv" (dict "root" $ "app" "hub-api") | nin
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
OpenTelemetry sampler env entries, rendered only when configured. The OTel SDKs
|
||||
read these natively; unset keeps the SDK default (parentbased_always_on).
|
||||
OpenTelemetry sampling env.
|
||||
"hub.opentelemetry.samplerEnv" is for the services that only continue traces
|
||||
started elsewhere (hub-workflows, pipe-*, workflow stages): they follow the
|
||||
parent's sampling decision and never start traces of their own.
|
||||
"hub.opentelemetry.apiSamplerEnv" renders hub-api's per-class sampling ratios
|
||||
(opentelemetry.apiSamplingRatios) as TRACE_SAMPLER_RATIO_<CLASS>; empty values
|
||||
are not rendered.
|
||||
Usage: {{- include "hub.opentelemetry.samplerEnv" $ | trim | nindent 8 }}
|
||||
*/}}
|
||||
{{- define "hub.opentelemetry.samplerEnv" -}}
|
||||
{{- with .Values.opentelemetry.sampler.type }}
|
||||
- name: OTEL_TRACES_SAMPLER
|
||||
value: {{ . | quote }}
|
||||
value: "parentbased_always_off"
|
||||
{{- end -}}
|
||||
|
||||
{{- define "hub.opentelemetry.apiSamplerEnv" -}}
|
||||
{{- range $class, $ratio := (.Values.opentelemetry.apiSamplingRatios | default dict) }}
|
||||
{{- if ne (toString $ratio) "" }}
|
||||
- name: TRACE_SAMPLER_RATIO_{{ upper $class }}
|
||||
value: {{ toString $ratio | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.opentelemetry.sampler.arg }}
|
||||
- name: OTEL_TRACES_SAMPLER_ARG
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
hub.audit.destinations resolves the audit destinations into JSON. Inline
|
||||
credentials (s3.accessKey / s3.secretKey on S3 destinations, bearerToken and
|
||||
secretHeaders.<name>.value on webhooks) are the only way to pass credentials.
|
||||
They are stored in a chart-created Secret named hub-audit-<id>-credentials;
|
||||
the internal credentialsSecret / bearerTokenSecret / secretHeaders entries
|
||||
below describe that Secret for the other templates.
|
||||
Use: fromJsonArray (include "hub.audit.destinations" .)
|
||||
*/}}
|
||||
{{- define "hub.audit.destinations" -}}
|
||||
{{- $resolved := list -}}
|
||||
{{- range $index, $original := .Values.kerberoshub.audit.destinations -}}
|
||||
{{- $destination := deepCopy $original -}}
|
||||
{{- $label := default (printf "%d" $index) $destination.id -}}
|
||||
{{- if hasKey $destination "credentialsSecret" -}}
|
||||
{{- fail (printf "audit destination %s: credentialsSecret is not supported; set s3.accessKey and s3.secretKey" $label) -}}
|
||||
{{- end -}}
|
||||
{{- if hasKey $destination "bearerTokenSecret" -}}
|
||||
{{- fail (printf "audit destination %s: bearerTokenSecret is not supported; set bearerToken" $label) -}}
|
||||
{{- end -}}
|
||||
{{- $s3 := default dict $destination.s3 -}}
|
||||
{{- if or (hasKey $s3 "accessKey") (hasKey $s3 "secretKey") -}}
|
||||
{{- $id := required (printf "id is required for audit destination %d" $index) $destination.id -}}
|
||||
{{- if not (and $s3.accessKey $s3.secretKey) -}}
|
||||
{{- fail (printf "audit destination %s must set both s3.accessKey and s3.secretKey, and neither may be empty" $id) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $destination "credentialsSecret" (dict
|
||||
"name" (printf "hub-audit-%s-credentials" $id)
|
||||
"create" true
|
||||
"accessKeyId" $s3.accessKey
|
||||
"secretAccessKey" $s3.secretKey) -}}
|
||||
{{- $_ := unset $s3 "accessKey" -}}
|
||||
{{- $_ := unset $s3 "secretKey" -}}
|
||||
{{- end -}}
|
||||
{{- if hasKey $destination "bearerToken" -}}
|
||||
{{- $id := required (printf "id is required for audit destination %d" $index) $destination.id -}}
|
||||
{{- if not $destination.bearerToken -}}
|
||||
{{- fail (printf "audit destination %s sets an empty bearerToken" $id) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $destination "bearerTokenSecret" (dict
|
||||
"name" (printf "hub-audit-%s-credentials" $id)
|
||||
"key" "bearer-token"
|
||||
"create" true
|
||||
"value" $destination.bearerToken) -}}
|
||||
{{- $_ := unset $destination "bearerToken" -}}
|
||||
{{- end -}}
|
||||
{{- range $header, $secret := (default dict $destination.secretHeaders) -}}
|
||||
{{- if or (not (kindIs "map" $secret)) (not (hasKey $secret "value")) (hasKey $secret "secretName") (hasKey $secret "secretKey") -}}
|
||||
{{- fail (printf "audit destination %s header %s: set secretHeaders.%s.value" $label $header $header) -}}
|
||||
{{- end -}}
|
||||
{{- $id := required (printf "id is required for audit destination %d" $index) $destination.id -}}
|
||||
{{- if not $secret.value -}}
|
||||
{{- fail (printf "audit destination %s header %s sets an empty value" $id $header) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $secret "secretName" (printf "hub-audit-%s-credentials" $id) -}}
|
||||
{{- $_ := set $secret "secretKey" (printf "header-%s" (sha256sum $header | trunc 12)) -}}
|
||||
{{- $_ := set $secret "create" true -}}
|
||||
{{- end -}}
|
||||
{{- $resolved = append $resolved $destination -}}
|
||||
{{- end -}}
|
||||
{{- toJson $resolved -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -26,6 +26,10 @@ spec:
|
||||
- name: admin
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.admin.repository }}:{{ .Values.admin.tag }}"
|
||||
imagePullPolicy: {{ .Values.admin.pullPolicy }}
|
||||
{{- with .Values.admin.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.admin.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
@@ -36,8 +40,16 @@ spec:
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
containerPort: {{ .Values.admin.containerPort | default 80 }}
|
||||
protocol: TCP
|
||||
{{- with .Values.admin.readinessProbe }}
|
||||
readinessProbe:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.admin.livenessProbe }}
|
||||
livenessProbe:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "{{ .Values.admin.logLevel }}"
|
||||
|
||||
@@ -10,7 +10,7 @@ spec:
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
targetPort: http
|
||||
name: http
|
||||
selector:
|
||||
app: admin
|
||||
|
||||
@@ -11,6 +11,28 @@
|
||||
{"key": "cell phone", "label": "Cell phone", "icon": "cell phone"}
|
||||
]
|
||||
{{- end -}}
|
||||
{{/*
|
||||
The effective chart-rendered catalog: the inline classificationCatalog values
|
||||
list when set, otherwise the bundled defaults above. values.schema.json
|
||||
validates each entry ({key, label, icon?}); keys must also be unique.
|
||||
*/}}
|
||||
{{- define "hub.classificationCatalog.json" -}}
|
||||
{{- if kindIs "invalid" .Values.classificationCatalog -}}
|
||||
{{- include "hub.classificationCatalog.defaults" . | mustFromJson | toJson -}}
|
||||
{{- else if and (kindIs "slice" .Values.classificationCatalog) .Values.classificationCatalog -}}
|
||||
{{- $seen := dict -}}
|
||||
{{- range $entry := .Values.classificationCatalog -}}
|
||||
{{- $key := toString $entry.key -}}
|
||||
{{- if hasKey $seen $key -}}
|
||||
{{- fail (printf "classificationCatalog: duplicate key %q" $key) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $seen $key true -}}
|
||||
{{- end -}}
|
||||
{{- .Values.classificationCatalog | toJson -}}
|
||||
{{- else -}}
|
||||
{{- fail "classificationCatalog must be omitted (bundled defaults) or a nonempty list; to use the API fallback set classificationCatalogEnabled: false" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $config := include "hub.workflowConfiguration.settings" . | fromYaml -}}
|
||||
{{- if and .Values.classificationCatalogEnabled (not .Values.classificationCatalogExistingConfigMap) (not (hasKey $config.replacements "catalogs/classifications.json")) }}
|
||||
apiVersion: v1
|
||||
@@ -20,5 +42,5 @@ metadata:
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
classifications.json: |-
|
||||
{{- include "hub.classificationCatalog.defaults" . | mustFromJson | toPrettyJson | nindent 4 }}
|
||||
{{- include "hub.classificationCatalog.json" . | mustFromJson | toPrettyJson | nindent 4 }}
|
||||
{{- end -}}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{{- if include "kerberoshub.deviceTags.system.enabled" . }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: device-system-tags
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
# Rendered from deviceTags.system.catalog; hub-api reads it through
|
||||
# DEVICE_SYSTEM_TAGS_FILE.
|
||||
system-tags.json: |-
|
||||
{{- include "kerberoshub.deviceTags.system.json" . | mustFromJson | toPrettyJson | nindent 4 }}
|
||||
{{- end -}}
|
||||
@@ -1,7 +1,7 @@
|
||||
{{- if .Values.audit.enabled -}}
|
||||
{{- $destinations := list -}}
|
||||
{{- $destinationIDs := dict -}}
|
||||
{{- range $index, $destination := .Values.kerberoshub.audit.destinations -}}
|
||||
{{- range $index, $destination := fromJsonArray (include "hub.audit.destinations" .) -}}
|
||||
{{- $id := required (printf "id is required for audit destination %d" $index) $destination.id -}}
|
||||
{{- if not (regexMatch "^[a-z][a-z0-9-]{0,62}$" $id) -}}
|
||||
{{- fail (printf "audit destination id %q must match ^[a-z][a-z0-9-]{0,62}$" $id) -}}
|
||||
@@ -10,33 +10,60 @@
|
||||
{{- fail (printf "duplicate audit destination id %q" $id) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $destinationIDs $id true -}}
|
||||
{{- $url := required (printf "url is required for audit destination %s" $id) $destination.url -}}
|
||||
{{- $type := default "webhook" $destination.type -}}
|
||||
{{- $entry := dict
|
||||
"id" $id
|
||||
"type" (default "webhook" $destination.type)
|
||||
"enabled" $destination.enabled
|
||||
"url" $url
|
||||
"type" $type
|
||||
"enabled" (ternary $destination.enabled true (hasKey $destination "enabled"))
|
||||
"timeoutSeconds" (default 10 $destination.timeoutSeconds)
|
||||
"batchSize" (default 100 $destination.batchSize)
|
||||
"maxAttempts" (default 10 $destination.maxAttempts)
|
||||
"startAt" (default "latest" $destination.startAt)
|
||||
"headers" (default dict $destination.headers)
|
||||
"filters" (default dict $destination.filters) -}}
|
||||
{{- $secretRoot := printf "/var/run/secrets/audit-destinations/%s" $id -}}
|
||||
{{- $bearer := default dict $destination.bearerTokenSecret -}}
|
||||
{{- if gt (len $bearer) 0 -}}
|
||||
{{- $secretName := required (printf "bearerTokenSecret.name is required for destination %s" $id) $bearer.name -}}
|
||||
{{- $secretKey := default "token" $bearer.key -}}
|
||||
{{- $_ := set $entry "bearerTokenFile" (printf "%s/bearer-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName $secretKey) | trunc 12)) -}}
|
||||
{{- end -}}
|
||||
{{- $headerFiles := dict -}}
|
||||
{{- range $headerName, $secret := (default dict $destination.secretHeaders) -}}
|
||||
{{- $secretName := required (printf "secretName is required for destination %s header %s" $id $headerName) $secret.secretName -}}
|
||||
{{- $secretKey := required (printf "secretKey is required for destination %s header %s" $id $headerName) $secret.secretKey -}}
|
||||
{{- $_ := set $headerFiles $headerName (printf "%s/header-%s" $secretRoot (sha256sum (printf "%s:%s:%s" $headerName $secretName $secretKey) | trunc 12)) -}}
|
||||
{{- end -}}
|
||||
{{- if gt (len $headerFiles) 0 -}}
|
||||
{{- $_ := set $entry "headerFiles" $headerFiles -}}
|
||||
{{- if eq $type "webhook" -}}
|
||||
{{- if or $destination.s3 $destination.credentialsSecret -}}
|
||||
{{- fail (printf "audit destination %s is a webhook and cannot set s3 or credentialsSecret" $id) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $entry "url" (required (printf "url is required for audit destination %s" $id) $destination.url) -}}
|
||||
{{- $_ := set $entry "headers" (default dict $destination.headers) -}}
|
||||
{{- $bearer := default dict $destination.bearerTokenSecret -}}
|
||||
{{- if gt (len $bearer) 0 -}}
|
||||
{{- $secretName := required (printf "bearerTokenSecret.name is required for destination %s" $id) $bearer.name -}}
|
||||
{{- $secretKey := default "token" $bearer.key -}}
|
||||
{{- $_ := set $entry "bearerTokenFile" (printf "%s/bearer-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName $secretKey) | trunc 12)) -}}
|
||||
{{- end -}}
|
||||
{{- $headerFiles := dict -}}
|
||||
{{- range $headerName, $secret := (default dict $destination.secretHeaders) -}}
|
||||
{{- $secretName := required (printf "secretName is required for destination %s header %s" $id $headerName) $secret.secretName -}}
|
||||
{{- $secretKey := required (printf "secretKey is required for destination %s header %s" $id $headerName) $secret.secretKey -}}
|
||||
{{- $_ := set $headerFiles $headerName (printf "%s/header-%s" $secretRoot (sha256sum (printf "%s:%s:%s" $headerName $secretName $secretKey) | trunc 12)) -}}
|
||||
{{- end -}}
|
||||
{{- if gt (len $headerFiles) 0 -}}
|
||||
{{- $_ := set $entry "headerFiles" $headerFiles -}}
|
||||
{{- end -}}
|
||||
{{- else if eq $type "s3" -}}
|
||||
{{- if or $destination.url $destination.headers $destination.bearerTokenSecret $destination.secretHeaders -}}
|
||||
{{- fail (printf "audit destination %s is s3 and cannot set url, headers, bearerToken, bearerTokenSecret or secretHeaders" $id) -}}
|
||||
{{- end -}}
|
||||
{{- $s3 := required (printf "s3 is required for audit destination %s" $id) $destination.s3 -}}
|
||||
{{- $settings := dict
|
||||
"bucket" (required (printf "s3.bucket is required for audit destination %s" $id) $s3.bucket)
|
||||
"region" (required (printf "s3.region is required for audit destination %s" $id) $s3.region) -}}
|
||||
{{- range $key := list "prefix" "endpoint" "forcePathStyle" "allowUnlockedBucket" -}}
|
||||
{{- if hasKey $s3 $key -}}
|
||||
{{- $_ := set $settings $key (get $s3 $key) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $credentials := default dict $destination.credentialsSecret -}}
|
||||
{{- if gt (len $credentials) 0 -}}
|
||||
{{- $secretName := required (printf "credentialsSecret.name is required for destination %s" $id) $credentials.name -}}
|
||||
{{- $_ := set $settings "accessKeyIdFile" (printf "%s/access-key-id-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName (default "access-key-id" $credentials.accessKeyIdKey)) | trunc 12)) -}}
|
||||
{{- $_ := set $settings "secretAccessKeyFile" (printf "%s/secret-access-key-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName (default "secret-access-key" $credentials.secretAccessKeyKey)) | trunc 12)) -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $entry "s3" $settings -}}
|
||||
{{- else -}}
|
||||
{{- fail (printf "audit destination %s has unsupported type %q (webhook or s3)" $id $type) -}}
|
||||
{{- end -}}
|
||||
{{- $destinations = append $destinations $entry -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -125,6 +125,9 @@ spec:
|
||||
{{- if and .Values.classificationCatalogEnabled (not .Values.classificationCatalogExistingConfigMap) (not $catalogReplacement) }}
|
||||
checksum/classification-catalog: {{ include (print $.Template.BasePath "/configMaps/catalogs/classifications.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if include "kerberoshub.deviceTags.system.enabled" . }}
|
||||
checksum/device-system-tags: {{ include (print $.Template.BasePath "/configMaps/catalogs/device-system-tags.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if and $workflowConfiguration.enabled $workflowConfiguration.includeDefaults (not (hasKey $workflowConfiguration.replacements "workflow-contracts/start.yaml")) }}
|
||||
checksum/workflow-configuration: {{ include (print $.Template.BasePath "/configMaps/workflow-contracts/start.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
@@ -137,6 +140,10 @@ spec:
|
||||
labels:
|
||||
app: hub-api
|
||||
spec:
|
||||
{{- with .Values.kerberoshub.api.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -147,7 +154,8 @@ spec:
|
||||
{{- $serverTLS := .Values.kerberoshub.api.serverTLS }}
|
||||
{{- $mongodbTLS := .Values.mongodb.tls }}
|
||||
{{- $classificationCatalogEnabled := .Values.classificationCatalogEnabled }}
|
||||
{{- if or $workflowConfiguration.enabled $classificationCatalogEnabled .Values.kerberoshub.api.volumes (and $serverTLS.enabled $serverTLS.secretName) (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
|
||||
{{- $deviceSystemTagsEnabled := include "kerberoshub.deviceTags.system.enabled" . }}
|
||||
{{- if or $workflowConfiguration.enabled $classificationCatalogEnabled $deviceSystemTagsEnabled .Values.kerberoshub.api.volumes (and $serverTLS.enabled $serverTLS.secretName) (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
|
||||
volumes:
|
||||
{{- if $workflowConfiguration.enabled }}
|
||||
- name: workflow-configuration
|
||||
@@ -200,6 +208,11 @@ spec:
|
||||
path: classifications.json
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $deviceSystemTagsEnabled }}
|
||||
- name: device-system-tags
|
||||
configMap:
|
||||
name: device-system-tags
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.api.volumes }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -220,6 +233,10 @@ spec:
|
||||
- name: hub-api
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.api.repository }}:{{ .Values.kerberoshub.api.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.api.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.api.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.api.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
@@ -227,7 +244,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
{{- if or $workflowConfiguration.enabled $classificationCatalogEnabled .Values.kerberoshub.api.volumeMounts (and $serverTLS.enabled $serverTLS.secretName) (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
|
||||
{{- if or $workflowConfiguration.enabled $classificationCatalogEnabled $deviceSystemTagsEnabled .Values.kerberoshub.api.volumeMounts (and $serverTLS.enabled $serverTLS.secretName) (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
|
||||
volumeMounts:
|
||||
{{- if $workflowConfiguration.enabled }}
|
||||
- name: workflow-configuration
|
||||
@@ -239,6 +256,11 @@ spec:
|
||||
mountPath: /etc/kerberos/classifications
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if $deviceSystemTagsEnabled }}
|
||||
- name: device-system-tags
|
||||
mountPath: /etc/kerberos/device-tags
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.api.volumeMounts}}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -261,6 +283,12 @@ spec:
|
||||
- name: CLASSIFICATION_CATALOG_FILE
|
||||
value: /etc/kerberos/classifications/classifications.json
|
||||
{{- end }}
|
||||
{{- if $deviceSystemTagsEnabled }}
|
||||
# System tag catalog (deviceTags.system.catalog): the only system
|
||||
# tags owners can assign. Unset (disabled) disables system tags.
|
||||
- name: DEVICE_SYSTEM_TAGS_FILE
|
||||
value: /etc/kerberos/device-tags/system-tags.json
|
||||
{{- end }}
|
||||
- name: ENVIRONMENT
|
||||
value: "{{ .Values.environment }}"
|
||||
- name: READ_ONLY
|
||||
@@ -275,6 +303,12 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.api.schema }}://{{ .Values.kerberoshub.api.url }}"
|
||||
- name: PUBLIC_URL
|
||||
value: "{{ .Values.kerberoshub.frontend.schema }}://{{ .Values.kerberoshub.frontend.url }}"
|
||||
- name: ACCESS_TOKEN_TIMEOUT
|
||||
value: {{ .Values.kerberoshub.api.session.accessTokenTimeout | quote }}
|
||||
- name: SESSION_IDLE_TIMEOUT
|
||||
value: {{ .Values.kerberoshub.api.session.idleTimeout | quote }}
|
||||
- name: SESSION_MAX_LIFETIME
|
||||
value: {{ .Values.kerberoshub.api.session.maxLifetime | quote }}
|
||||
- name: REFRESH_COOKIE_SECURE
|
||||
value: {{ eq .Values.kerberoshub.api.schema "https" | quote }}
|
||||
{{- $corsOrigins := list (printf "%s://%s" .Values.kerberoshub.frontend.schema .Values.kerberoshub.frontend.url) }}
|
||||
@@ -295,6 +329,11 @@ spec:
|
||||
{{- end }}
|
||||
- name: CORS_ALLOWED_ORIGINS
|
||||
value: {{ join "," $corsOrigins | quote }}
|
||||
{{- $mcp := .Values.kerberoshub.api.mcp | default dict }}
|
||||
- name: MCP_ENABLED
|
||||
value: {{ $mcp.enabled | default false | quote }}
|
||||
- name: MCP_ALLOWED_ORIGINS
|
||||
value: {{ join "," ($mcp.allowedOrigins | default list) | quote }}
|
||||
{{ if .Values.isPrivate }}
|
||||
- name: KERBEROS_PRIVATE_CLOUD
|
||||
value: "true"
|
||||
@@ -416,6 +455,17 @@ spec:
|
||||
- name: MFA_ISSUER
|
||||
value: "{{ .Values.kerberoshub.api.mfaIssuer }}"
|
||||
|
||||
{{- if .Values.kerberoshub.api.passkeys.enabled }}
|
||||
- name: FEATURE_PASSKEYS_ENABLED
|
||||
value: "true"
|
||||
- name: PASSKEY_RP_ID
|
||||
value: {{ required "kerberoshub.api.passkeys.rpId is required when passkeys are enabled" .Values.kerberoshub.api.passkeys.rpId | quote }}
|
||||
- name: PASSKEY_ORIGINS
|
||||
value: {{ required "kerberoshub.api.passkeys.origins is required when passkeys are enabled" .Values.kerberoshub.api.passkeys.origins | join "," | quote }}
|
||||
- name: PASSKEY_RP_NAME
|
||||
value: {{ .Values.kerberoshub.api.passkeys.rpName | quote }}
|
||||
{{- end }}
|
||||
|
||||
# AWS (Legacy, use Kerberos Vault instead)
|
||||
- name: AWS_REGION
|
||||
value: "{{ .Values.kerberoshub.api.aws.region }}"
|
||||
@@ -522,6 +572,10 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.api.defaultTaskRetentionDays }}"
|
||||
- name: CASES_MAX_RETENTION_DAYS
|
||||
value: "{{ .Values.kerberoshub.api.casesMaxRetentionDays }}"
|
||||
{{- with .Values.kerberoshub.api.auditExportMaxEventsPerFile }}
|
||||
- name: AUDIT_EXPORT_MAX_EVENTS_PER_FILE
|
||||
value: {{ . | int64 | toString | quote }}
|
||||
{{- end }}
|
||||
|
||||
# SMTP
|
||||
- name: SMTP_SERVER
|
||||
@@ -577,6 +631,6 @@ spec:
|
||||
value: "{{ .Values.opentelemetry.routingEnabled }}"
|
||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
value: "{{ .Values.opentelemetry.collector.endpoint }}"
|
||||
{{- include "hub.opentelemetry.samplerEnv" $ | trim | nindent 12 }}
|
||||
{{- include "hub.opentelemetry.apiSamplerEnv" $ | trim | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- if .Values.audit.enabled }}
|
||||
{{- /*
|
||||
Secret the chart creates per audit destination from its inline credentials
|
||||
(s3.accessKey / s3.secretKey, bearerToken, secretHeaders.<name>.value).
|
||||
*/}}
|
||||
{{- $created := dict }}
|
||||
{{- range $index, $destination := fromJsonArray (include "hub.audit.destinations" .) }}
|
||||
{{- $data := dict }}
|
||||
{{- $name := "" }}
|
||||
{{- $credentials := default dict $destination.credentialsSecret }}
|
||||
{{- if $credentials.create }}
|
||||
{{- $name = required (printf "credentialsSecret.name is required for destination %s" $destination.id) $credentials.name }}
|
||||
{{- $accessKeyIdKey := default "access-key-id" $credentials.accessKeyIdKey }}
|
||||
{{- $secretAccessKeyKey := default "secret-access-key" $credentials.secretAccessKeyKey }}
|
||||
{{- if eq $accessKeyIdKey $secretAccessKeyKey }}
|
||||
{{- fail (printf "credentialsSecret.accessKeyIdKey and secretAccessKeyKey must differ for destination %s" $destination.id) }}
|
||||
{{- end }}
|
||||
{{- $_ := set $data $accessKeyIdKey (required (printf "credentialsSecret.accessKeyId is required for destination %s when credentialsSecret.create is true" $destination.id) $credentials.accessKeyId) }}
|
||||
{{- $_ := set $data $secretAccessKeyKey (required (printf "credentialsSecret.secretAccessKey is required for destination %s when credentialsSecret.create is true" $destination.id) $credentials.secretAccessKey) }}
|
||||
{{- end }}
|
||||
{{- $bearer := default dict $destination.bearerTokenSecret }}
|
||||
{{- if $bearer.create }}
|
||||
{{- $name = $bearer.name }}
|
||||
{{- $_ := set $data $bearer.key $bearer.value }}
|
||||
{{- end }}
|
||||
{{- range $header, $secret := (default dict $destination.secretHeaders) }}
|
||||
{{- if $secret.create }}
|
||||
{{- $name = $secret.secretName }}
|
||||
{{- $_ := set $data $secret.secretKey $secret.value }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $name }}
|
||||
{{- if hasKey $created $name }}
|
||||
{{- fail (printf "audit destinations %s and %s both create Secret %q" (get $created $name) $destination.id $name) }}
|
||||
{{- end }}
|
||||
{{- $_ := set $created $name $destination.id }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ $name }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
labels:
|
||||
app: hub-audit
|
||||
audit-destination: {{ $destination.id }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
{{- range $key, $value := $data }}
|
||||
{{ $key | quote }}: {{ toString $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{- if and .Values.audit.enabled (default dict .Values.kerberoshub.audit.serviceAccount).create }}
|
||||
{{- $serviceAccount := .Values.kerberoshub.audit.serviceAccount }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ default "hub-audit" $serviceAccount.name }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- with $serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with $serviceAccount.labels }}
|
||||
labels:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -26,7 +26,12 @@ spec:
|
||||
app: hub-audit
|
||||
spec:
|
||||
terminationGracePeriodSeconds: {{ .Values.kerberoshub.audit.terminationGracePeriodSeconds }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
{{- $auditServiceAccount := default dict .Values.kerberoshub.audit.serviceAccount }}
|
||||
{{- if $auditServiceAccount.create }}
|
||||
serviceAccountName: {{ default "hub-audit" $auditServiceAccount.name }}
|
||||
{{- else if $auditServiceAccount.name }}
|
||||
serviceAccountName: {{ $auditServiceAccount.name }}
|
||||
{{- else if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
@@ -38,13 +43,25 @@ spec:
|
||||
- name: destinations
|
||||
configMap:
|
||||
name: hub-audit
|
||||
{{- range $index, $destination := .Values.kerberoshub.audit.destinations }}
|
||||
{{- range $index, $destination := fromJsonArray (include "hub.audit.destinations" $) }}
|
||||
{{- $bearer := default dict $destination.bearerTokenSecret }}
|
||||
{{- $secretHeaders := default dict $destination.secretHeaders }}
|
||||
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) }}
|
||||
{{- $credentials := default dict $destination.credentialsSecret }}
|
||||
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) (gt (len $credentials) 0) }}
|
||||
- name: audit-dest-{{ sha256sum $destination.id | trunc 12 }}
|
||||
projected:
|
||||
sources:
|
||||
{{- if gt (len $credentials) 0 }}
|
||||
{{- $accessKeyIdKey := default "access-key-id" $credentials.accessKeyIdKey }}
|
||||
{{- $secretAccessKeyKey := default "secret-access-key" $credentials.secretAccessKeyKey }}
|
||||
- secret:
|
||||
name: {{ required (printf "credentialsSecret.name is required for destination %s" $destination.id) $credentials.name | quote }}
|
||||
items:
|
||||
- key: {{ $accessKeyIdKey | quote }}
|
||||
path: access-key-id-{{ sha256sum (printf "%s:%s" $credentials.name $accessKeyIdKey) | trunc 12 }}
|
||||
- key: {{ $secretAccessKeyKey | quote }}
|
||||
path: secret-access-key-{{ sha256sum (printf "%s:%s" $credentials.name $secretAccessKeyKey) | trunc 12 }}
|
||||
{{- end }}
|
||||
{{- if gt (len $bearer) 0 }}
|
||||
- secret:
|
||||
name: {{ required (printf "bearerTokenSecret.name is required for destination %s" $destination.id) $bearer.name | quote }}
|
||||
@@ -95,10 +112,11 @@ spec:
|
||||
- name: destinations
|
||||
mountPath: /etc/hub-audit
|
||||
readOnly: true
|
||||
{{- range $index, $destination := .Values.kerberoshub.audit.destinations }}
|
||||
{{- range $index, $destination := fromJsonArray (include "hub.audit.destinations" $) }}
|
||||
{{- $bearer := default dict $destination.bearerTokenSecret }}
|
||||
{{- $secretHeaders := default dict $destination.secretHeaders }}
|
||||
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) }}
|
||||
{{- $credentials := default dict $destination.credentialsSecret }}
|
||||
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) (gt (len $credentials) 0) }}
|
||||
- name: audit-dest-{{ sha256sum $destination.id | trunc 12 }}
|
||||
mountPath: /var/run/secrets/audit-destinations/{{ $destination.id }}
|
||||
readOnly: true
|
||||
|
||||
@@ -22,6 +22,10 @@ spec:
|
||||
labels:
|
||||
app: hub-cleanup
|
||||
spec:
|
||||
{{- with .Values.kerberoshub.cleanup.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -47,6 +51,10 @@ spec:
|
||||
- name: hub-cleanup
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.cleanup.repository }}:{{ .Values.kerberoshub.cleanup.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.cleanup.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.cleanup.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.cleanup.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
@@ -10,7 +10,7 @@ spec:
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
targetPort: http
|
||||
name: http
|
||||
selector:
|
||||
app: hub-frontend-demo
|
||||
@@ -101,12 +101,16 @@ spec:
|
||||
- name: hub-frontend-demo
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.frontend.repository }}:{{ .Values.kerberoshub.frontend.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.frontend.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.frontend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.frontend.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- containerPort: {{ .Values.kerberoshub.frontend.containerPort | default 8080 }}
|
||||
name: http
|
||||
{{- with .Values.kerberoshub.frontend.volumeMounts}}
|
||||
volumeMounts:
|
||||
@@ -192,6 +196,8 @@ spec:
|
||||
# Google maps for using and displaying cameras, sites on a map
|
||||
- name: GOOGLEMAPS_KEY
|
||||
value: "{{ .Values.kerberoshub.frontend.googlemaps.apikey }}"
|
||||
- name: GOOGLEMAPS_PLACES_API
|
||||
value: "{{ .Values.kerberoshub.frontend.googlemaps.placesApi }}"
|
||||
|
||||
# features > chart
|
||||
- name: CHART_COLORS
|
||||
@@ -235,6 +241,8 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.frontend.features.workflows.enabled }}"
|
||||
- name: FEATURE_AUDIT_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.audit.enabled }}"
|
||||
- name: FEATURE_PASSKEYS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.api.passkeys.enabled }}"
|
||||
- name: FEATURE_DAY_OVERVIEW_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.dayOverview.enabled }}"
|
||||
- name: FEATURE_DEVICE_ANALYTICS_ENABLED
|
||||
@@ -251,6 +259,8 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.frontend.features.organisations.creationEnabled }}"
|
||||
- name: FEATURE_ORGANISATION_SETTINGS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.organisations.settingsEnabled }}"
|
||||
- name: FEATURE_MEMBERS_ACCESS_PREVIEW_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.organisations.membersAccessPreviewEnabled }}"
|
||||
- name: FEATURE_PROJECTS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.projects.enabled }}"
|
||||
- name: FEATURE_PROJECT_SWITCHER_ENABLED
|
||||
@@ -359,6 +369,10 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.frontend.features.faceRedaction.classifierTracksEnabled }}"
|
||||
|
||||
# features > media
|
||||
- name: FEATURE_MEDIA_FORWARD_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.media.forward.enabled }}"
|
||||
- name: FEATURE_MEDIA_DETAIL_ANALYSIS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.media.detail.analysis.enabled }}"
|
||||
- name: FEATURE_MEDIA_FILTER_DATE_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.media.filter.date.enabled }}"
|
||||
- name: FEATURE_MEDIA_FILTER_SITES_ENABLED
|
||||
|
||||
@@ -11,7 +11,7 @@ spec:
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
targetPort: http
|
||||
name: http
|
||||
selector:
|
||||
app: hub-frontend
|
||||
@@ -182,12 +182,16 @@ spec:
|
||||
- name: hub-frontend
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.frontend.repository }}:{{ .Values.kerberoshub.frontend.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.frontend.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.frontend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.frontend.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- containerPort: {{ .Values.kerberoshub.frontend.containerPort | default 8080 }}
|
||||
name: http
|
||||
{{- with .Values.kerberoshub.frontend.volumeMounts}}
|
||||
volumeMounts:
|
||||
@@ -275,6 +279,8 @@ spec:
|
||||
# Google maps for using and displaying cameras, sites on a map
|
||||
- name: GOOGLEMAPS_KEY
|
||||
value: "{{ .Values.kerberoshub.frontend.googlemaps.apikey }}"
|
||||
- name: GOOGLEMAPS_PLACES_API
|
||||
value: "{{ .Values.kerberoshub.frontend.googlemaps.placesApi }}"
|
||||
|
||||
# Zendesk for support
|
||||
- name: ZENDESK_URL
|
||||
@@ -314,6 +320,8 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.frontend.features.workflows.enabled }}"
|
||||
- name: FEATURE_AUDIT_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.audit.enabled }}"
|
||||
- name: FEATURE_PASSKEYS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.api.passkeys.enabled }}"
|
||||
- name: FEATURE_DAY_OVERVIEW_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.dayOverview.enabled }}"
|
||||
- name: FEATURE_DEVICE_ANALYTICS_ENABLED
|
||||
@@ -330,6 +338,8 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.frontend.features.organisations.creationEnabled }}"
|
||||
- name: FEATURE_ORGANISATION_SETTINGS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.organisations.settingsEnabled }}"
|
||||
- name: FEATURE_MEMBERS_ACCESS_PREVIEW_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.organisations.membersAccessPreviewEnabled }}"
|
||||
- name: FEATURE_PROJECTS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.projects.enabled }}"
|
||||
- name: FEATURE_PROJECT_SWITCHER_ENABLED
|
||||
@@ -451,6 +461,10 @@ spec:
|
||||
value: "{{ .Values.kerberoshub.frontend.features.faceRedaction.classifierTracksEnabled }}"
|
||||
|
||||
# features > media
|
||||
- name: FEATURE_MEDIA_FORWARD_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.media.forward.enabled }}"
|
||||
- name: FEATURE_MEDIA_DETAIL_ANALYSIS_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.media.detail.analysis.enabled }}"
|
||||
- name: FEATURE_MEDIA_FILTER_DATE_ENABLED
|
||||
value: "{{ .Values.kerberoshub.frontend.features.media.filter.date.enabled }}"
|
||||
- name: FEATURE_MEDIA_FILTER_SITES_ENABLED
|
||||
|
||||
@@ -22,6 +22,10 @@ spec:
|
||||
labels:
|
||||
app: hub-monitor-device
|
||||
spec:
|
||||
{{- with .Values.kerberoshub.monitordevice.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -47,6 +51,10 @@ spec:
|
||||
- name: hub-monitor-device
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.monitordevice.repository }}:{{ .Values.kerberoshub.monitordevice.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.monitordevice.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.monitordevice.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.monitordevice.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
@@ -67,6 +75,8 @@ spec:
|
||||
{{- include "hub.mongodb.appUriEnv" (dict "root" $ "app" "hub-monitor-device") | nindent 12 }}
|
||||
- name: LOG_LEVEL
|
||||
value: "{{ .Values.kerberoshub.monitordevice.logLevel }}"
|
||||
- name: DEVICE_SCAN_INTERVAL_SECONDS
|
||||
value: "{{ .Values.kerberoshub.monitordevice.scanIntervalSeconds | default 60 }}"
|
||||
- name: READ_ONLY
|
||||
value: "{{ .Values.readonly }}"
|
||||
# Mail settings
|
||||
@@ -82,6 +92,21 @@ spec:
|
||||
value: "{{ .Values.email.templates.device }}"
|
||||
- name: DEVICE_TITLE
|
||||
value: "{{ .Values.email.templates.deviceTitle }}"
|
||||
- name: DEVICE_GROUP_TEMPLATE
|
||||
value: "{{ .Values.email.templates.deviceGroup | default "device_group" }}"
|
||||
- name: DEVICE_GROUP_TITLE
|
||||
value: "{{ .Values.email.templates.deviceGroupTitle | default "[Device] Several cameras changed status" }}"
|
||||
{{- with .Values.email.templates.recording }}
|
||||
- name: RECORDING_TEMPLATE
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.email.templates.recordingTitle }}
|
||||
- name: RECORDING_TITLE
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
# Base URL for the link in grouped device notifications.
|
||||
- name: PUBLIC_URL
|
||||
value: "{{ .Values.kerberoshub.frontend.schema }}://{{ .Values.kerberoshub.frontend.url }}"
|
||||
|
||||
# - Plain SMTP
|
||||
- name: SMTP_SERVER
|
||||
|
||||
@@ -21,6 +21,64 @@ workflow later cannot silently alias another workflow's runs or references.
|
||||
{{- end -}}
|
||||
{{- $_ := set $identities $id $name -}}
|
||||
{{- end -}}
|
||||
{{- include "kerberoshub.workflows.validateSystemTags" . -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Guard the definitions that can select devices by system tag. The engine reads
|
||||
JSON keys case-insensitively and ignores unknown ones, so a misspelled or
|
||||
re-cased key silently changes what a definition selects (a dropped
|
||||
systemTags scope makes a global workflow run on every device). Therefore:
|
||||
- definitions and triggers may only use the keys the engine knows, spelled
|
||||
exactly (definition: id, enabled, triggers, stages; trigger: the
|
||||
models.WorkflowTrigger fields);
|
||||
- while deviceTags.system.enabled is false, no definition may mention system
|
||||
tags anywhere (trigger systemTags, or a device.systemTags condition at any
|
||||
depth, in triggers, shared conditions or stage needs), matched
|
||||
case-insensitively on the whole definition;
|
||||
- every system tag a trigger selects must be in deviceTags.system.catalog,
|
||||
so a typo fails rendering instead of never matching a device.
|
||||
Disabled definitions are checked too, so enabling one cannot fail later.
|
||||
*/}}
|
||||
{{- define "kerberoshub.workflows.validateSystemTags" -}}
|
||||
{{- include "kerberoshub.deviceTags.system.validate" . -}}
|
||||
{{- $catalog := dict -}}
|
||||
{{- range $tag := (include "kerberoshub.deviceTags.system.catalog" . | fromJsonArray) -}}
|
||||
{{- $_ := set $catalog (toString $tag.key) true -}}
|
||||
{{- end -}}
|
||||
{{- $enabled := include "kerberoshub.deviceTags.system.enabled" . -}}
|
||||
{{- $definitionKeys := list "id" "enabled" "triggers" "stages" -}}
|
||||
{{- $triggerKeys := list "type" "edgeId" "sharedConditions" "devices" "siteIds" "groupIds" "systemTags" "classifications" "conditionMode" "conditions" "weeklySchedule" "surfaces" -}}
|
||||
{{- range $name, $wf := .Values.kerberoshub.workflows.definitions -}}
|
||||
{{- if $wf -}}
|
||||
{{- if not (kindIs "map" $wf) -}}
|
||||
{{- fail (printf "kerberoshub.workflows.definitions[%q] must be an object" $name) -}}
|
||||
{{- end -}}
|
||||
{{- if and (not $enabled) (contains "systemtags" (lower (toJson $wf))) -}}
|
||||
{{- fail (printf "kerberoshub.workflows.definitions[%q] selects devices by system tag (systemTags or a device.systemTags condition), but deviceTags.system.enabled is false" $name) -}}
|
||||
{{- end -}}
|
||||
{{- range $key, $_ := $wf -}}
|
||||
{{- if not (has $key $definitionKeys) -}}
|
||||
{{- fail (printf "kerberoshub.workflows.definitions[%q]: unknown key %q (allowed: %s). Keys are case-sensitive; a misspelled key would be ignored" $name $key (join ", " $definitionKeys)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- range $i, $trigger := ($wf.triggers | default list) -}}
|
||||
{{- if not (kindIs "map" $trigger) -}}
|
||||
{{- fail (printf "kerberoshub.workflows.definitions[%q].triggers[%d] must be an object" $name $i) -}}
|
||||
{{- end -}}
|
||||
{{- range $key, $_ := $trigger -}}
|
||||
{{- if not (has $key $triggerKeys) -}}
|
||||
{{- fail (printf "kerberoshub.workflows.definitions[%q].triggers[%d]: unknown key %q (allowed: %s). Keys are case-sensitive; a misspelled key would be ignored and widen the trigger" $name $i $key (join ", " $triggerKeys)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- range $tag := ($trigger.systemTags | default list) -}}
|
||||
{{- if not (hasKey $catalog (toString $tag)) -}}
|
||||
{{- fail (printf "kerberoshub.workflows.definitions[%q].triggers[%d].systemTags: %q is not in deviceTags.system.catalog; add it to the system tag catalog" $name $i (toString $tag)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
|
||||
@@ -50,6 +50,10 @@ spec:
|
||||
labels:
|
||||
app: hub-{{ $name }}
|
||||
spec:
|
||||
{{- with $svc.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if $root.Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" $root.Release.Name $root.Chart.Name | trunc 63 | trimSuffix "-") $root.Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -69,6 +73,10 @@ spec:
|
||||
- name: hub-{{ $name }}
|
||||
image: "{{ $root.Values.global.imageRegistry }}{{ $svc.repository }}:{{ $svc.tag }}"
|
||||
imagePullPolicy: {{ $svc.pullPolicy | default "IfNotPresent" }}
|
||||
{{- with $svc.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with $svc.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
@@ -117,6 +125,14 @@ spec:
|
||||
- name: KERBEROS_STORAGE_PROVIDER
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- if $root.Values.opentelemetry.enabled }}
|
||||
|
||||
# OpenTelemetry tracing: the stage continues the engine's dispatch span
|
||||
# (the run's traceparent) and follows its sampling decision.
|
||||
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
value: "{{ $root.Values.opentelemetry.collector.endpoint }}"
|
||||
{{- include "hub.opentelemetry.samplerEnv" $root | trim | nindent 8 }}
|
||||
{{- end }}
|
||||
|
||||
# Per-stage tuning knobs. Any key/value under services.<name>.env is
|
||||
# rendered verbatim as container env, so a worker can be tuned from
|
||||
|
||||
@@ -23,6 +23,10 @@ spec:
|
||||
labels:
|
||||
app: hub-workflows
|
||||
spec:
|
||||
{{- with .Values.kerberoshub.services.workflows.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -48,6 +52,10 @@ spec:
|
||||
- name: hub-workflows
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.services.workflows.repository }}:{{ .Values.kerberoshub.services.workflows.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.services.workflows.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.services.workflows.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.services.workflows.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
@@ -126,6 +126,14 @@ spec:
|
||||
- name: DOMINANTCOLOR_ENABLED
|
||||
value: "{{ .Values.kerberospipeline.dominantColor.enabled }}"
|
||||
|
||||
# Thumbnail regeneration from classified frames (opt-in)
|
||||
- name: THUMBNAIL_REGENERATION_ENABLED
|
||||
value: {{ .Values.kerberospipeline.analysis.thumbnailRegeneration.enabled | default false | quote }}
|
||||
# Skip regeneration when the object first appears within this many seconds
|
||||
- name: THUMBNAIL_REGENERATION_MIN_SECONDS
|
||||
{{- $regeneration := .Values.kerberospipeline.analysis.thumbnailRegeneration }}
|
||||
value: {{ ternary $regeneration.minSeconds 3 (hasKey $regeneration "minSeconds") | quote }}
|
||||
|
||||
# In-memory cache for hot-path MongoDB lookups
|
||||
- name: DB_CACHE_ENABLED
|
||||
value: {{ .Values.kerberospipeline.analysis.dbCache.enabled | default false | quote }}
|
||||
|
||||
@@ -24,6 +24,10 @@ spec:
|
||||
labels:
|
||||
app: pipe-counting
|
||||
spec:
|
||||
{{- with .Values.kerberospipeline.counting.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -43,6 +47,10 @@ spec:
|
||||
- name: pipe-counting
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberospipeline.counting.repository }}:{{ .Values.kerberospipeline.counting.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberospipeline.counting.pullPolicy }}
|
||||
{{- with .Values.kerberospipeline.counting.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberospipeline.counting.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
@@ -24,6 +24,10 @@ spec:
|
||||
labels:
|
||||
app: pipe-dominantcolor
|
||||
spec:
|
||||
{{- with .Values.kerberospipeline.dominantColor.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -43,6 +47,10 @@ spec:
|
||||
- name: pipe-dominantcolor
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberospipeline.dominantColor.repository }}:{{ .Values.kerberospipeline.dominantColor.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberospipeline.dominantColor.pullPolicy }}
|
||||
{{- with .Values.kerberospipeline.dominantColor.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberospipeline.dominantColor.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
@@ -26,6 +26,10 @@ spec:
|
||||
labels:
|
||||
app: pipe-notify
|
||||
spec:
|
||||
{{- with .Values.kerberospipeline.notify.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -51,6 +55,10 @@ spec:
|
||||
- name: pipe-notify
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberospipeline.notify.repository }}:{{ .Values.kerberospipeline.notify.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberospipeline.notify.pullPolicy }}
|
||||
{{- with .Values.kerberospipeline.notify.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberospipeline.notify.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
@@ -69,6 +69,8 @@ spec:
|
||||
name: mongodb-config
|
||||
env:
|
||||
{{- include "hub.mongodb.appUriEnv" (dict "root" $ "app" "hub-pipeline-sequence") | nindent 8 }}
|
||||
- name: LOG_LEVEL
|
||||
value: "{{ .Values.kerberospipeline.sequence.logLevel }}"
|
||||
- name: CLOUD_PROVIDER
|
||||
value: "{{ .Values.cloudProvider }}"
|
||||
- name: QUEUE_SYSTEM
|
||||
|
||||
@@ -26,6 +26,10 @@ spec:
|
||||
labels:
|
||||
app: pipe-throttler
|
||||
spec:
|
||||
{{- with .Values.kerberospipeline.throttler.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -51,6 +55,10 @@ spec:
|
||||
- name: pipe-throttler
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberospipeline.throttler.repository }}:{{ .Values.kerberospipeline.throttler.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberospipeline.throttler.pullPolicy }}
|
||||
{{- with .Values.kerberospipeline.throttler.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberospipeline.throttler.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
@@ -24,6 +24,10 @@ spec:
|
||||
labels:
|
||||
app: pipe-thumbnail
|
||||
spec:
|
||||
{{- with .Values.kerberospipeline.thumbnail.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -43,6 +47,10 @@ spec:
|
||||
- name: pipe-thumbnail
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberospipeline.thumbnail.repository }}:{{ .Values.kerberospipeline.thumbnail.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberospipeline.thumbnail.pullPolicy }}
|
||||
{{- with .Values.kerberospipeline.thumbnail.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberospipeline.thumbnail.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
@@ -99,6 +107,8 @@ spec:
|
||||
value: "{{ .Values.kerberospipeline.thumbnail.width }}"
|
||||
- name: THUMBNAIL_HEIGHT
|
||||
value: "{{ .Values.kerberospipeline.thumbnail.height }}"
|
||||
- name: THUMBNAIL_SKIP_NON_KEYFRAMES
|
||||
value: "{{ .Values.kerberospipeline.thumbnail.skipNonKeyframes }}"
|
||||
|
||||
# There is an option to store the thumbnails in a storage provider in Kerberos Vault.
|
||||
# This will lower storage in mongodb.
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
# If .Values.kerberoshub.forwarder.enabled is set to true
|
||||
{{- if and (eq .Values.mode "all") .Values.kerberoshub.forwarder.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: vault-forwarder
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vault-forwarder
|
||||
minReadySeconds: 10
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
maxSurge: 1
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configMaps/configmap-mongodb.yaml") . | sha256sum }}
|
||||
labels:
|
||||
app: vault-forwarder
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- $mongodbTLS := .Values.mongodb.tls }}
|
||||
{{- if or .Values.kerberoshub.forwarder.volumes (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
|
||||
volumes:
|
||||
{{- with .Values.kerberoshub.forwarder.volumes }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if and $mongodbTLS.enabled $mongodbTLS.existingSecret }}
|
||||
{{- include "hub.mongodb.tlsVolume" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.forwarder.topologySpreadConstraints }}
|
||||
topologySpreadConstraints:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: vault-forwarder
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.forwarder.repository }}:{{ .Values.kerberoshub.forwarder.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.forwarder.pullPolicy }}
|
||||
resources:
|
||||
requests:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
{{- if or .Values.kerberoshub.forwarder.volumeMounts (and $mongodbTLS.enabled $mongodbTLS.existingSecret) }}
|
||||
volumeMounts:
|
||||
{{- with .Values.kerberoshub.forwarder.volumeMounts }}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if and $mongodbTLS.enabled $mongodbTLS.existingSecret }}
|
||||
{{- include "hub.mongodb.tlsVolumeMount" . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: mongodb-config
|
||||
env:
|
||||
{{- include "hub.mongodb.appUriEnv" (dict "root" $ "app" "vault-forwarder") | nindent 10 }}
|
||||
- name: ITERATION_SPEED
|
||||
value: "5"
|
||||
- name: BUFFER_TIME
|
||||
value: "3"
|
||||
- name: MQTT_URI
|
||||
value: "{{ .Values.mqtt.host }}"
|
||||
- name: MQTT_USERNAME
|
||||
value: "{{ .Values.mqtt.username }}"
|
||||
- name: MQTT_PASSWORD
|
||||
value: "{{ .Values.mqtt.password }}"
|
||||
{{- end }}
|
||||
@@ -1,78 +0,0 @@
|
||||
{{- if and (eq .Values.mode "all") .Values.kerberoshub.proxy.enabled -}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: vault-proxy
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
replicas: {{ .Values.kerberoshub.proxy.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: vault-proxy
|
||||
minReadySeconds: 10
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
maxSurge: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: vault-proxy
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.proxy.volumes }}
|
||||
volumes:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.proxy.topologySpreadConstraints }}
|
||||
topologySpreadConstraints:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: vault-proxy
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.proxy.repository }}:{{ .Values.kerberoshub.proxy.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.proxy.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.proxy.volumeMounts }}
|
||||
volumeMounts:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "{{ .Values.kerberoshub.proxy.logLevel }}"
|
||||
# Kerberos Hub API
|
||||
- name: KERBEROS_API_CHECK_SUBSCRIPTION
|
||||
value: "{{ .Values.kerberoshub.api.schema }}://{{ .Values.kerberoshub.api.url }}/user/has-subscription"
|
||||
# Kerberos Vault
|
||||
- name: KSTORAGE_URI
|
||||
value: "{{ .Values.kerberosvault.uri }}/storage"
|
||||
- name: KSTORAGE_ACCESSKEY
|
||||
value: "{{ .Values.kerberosvault.accesskey }}"
|
||||
- name: KSTORAGE_SECRET
|
||||
value: "{{ .Values.kerberosvault.secretkey }}"
|
||||
- name: KSTORAGE_PROVIDER
|
||||
value: "{{ .Values.kerberosvault.provider }}"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: vault-proxy-svc
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app: vault-proxy-svc
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
name: http
|
||||
selector:
|
||||
app: vault-proxy
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
admin images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/admin.
|
||||
The signature itself is checked by admin-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: admin-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: admin images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop admin pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-admin-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/admin:*"
|
||||
- "ghcr.io/uug-ai/admin@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/admin
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/admin
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
admin images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/admin.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: admin-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: admin images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop admin pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-admin
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/admin:*"
|
||||
- "ghcr.io/uug-ai/admin@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to admin's own repository.
|
||||
githubWorkflowRepository: uug-ai/admin
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-api images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-api.
|
||||
The signature itself is checked by hub-api-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-api-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-api images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-api pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-api-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-api:*"
|
||||
- "ghcr.io/uug-ai/hub-api@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-api
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-api
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-api images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-api.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-api-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-api images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-api pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-api
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-api:*"
|
||||
- "ghcr.io/uug-ai/hub-api@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-api's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-api
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-audit images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-audit.
|
||||
The signature itself is checked by hub-audit-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-audit-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-audit images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-audit pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-audit-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-audit:*"
|
||||
- "ghcr.io/uug-ai/hub-audit@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-audit
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-audit
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-audit images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-audit.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-audit-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-audit images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-audit pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-audit
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-audit:*"
|
||||
- "ghcr.io/uug-ai/hub-audit@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-audit's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-audit
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-cleanup images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-cleanup.
|
||||
The signature itself is checked by hub-cleanup-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-cleanup-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-cleanup images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-cleanup pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-cleanup-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-cleanup:*"
|
||||
- "ghcr.io/uug-ai/hub-cleanup@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-cleanup
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-cleanup
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-cleanup images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-cleanup.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-cleanup-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-cleanup images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-cleanup pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-cleanup
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-cleanup:*"
|
||||
- "ghcr.io/uug-ai/hub-cleanup@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-cleanup's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-cleanup
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-frontend images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-frontend.
|
||||
The signature itself is checked by hub-frontend-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-frontend-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-frontend images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-frontend pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-frontend-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-frontend:*"
|
||||
- "ghcr.io/uug-ai/hub-frontend@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-frontend
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-frontend
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-frontend images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-frontend.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-frontend-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-frontend images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-frontend pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-frontend
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-frontend:*"
|
||||
- "ghcr.io/uug-ai/hub-frontend@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-frontend's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-frontend
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-loitering images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-loitering.
|
||||
The signature itself is checked by hub-loitering-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-loitering-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-loitering images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-loitering pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-loitering-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-loitering:*"
|
||||
- "ghcr.io/uug-ai/hub-loitering@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-loitering
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-loitering
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-loitering images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-loitering.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-loitering-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-loitering images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-loitering pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-loitering
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-loitering:*"
|
||||
- "ghcr.io/uug-ai/hub-loitering@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-loitering's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-loitering
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-monitor-device images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-monitor-device.
|
||||
The signature itself is checked by hub-monitor-device-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-monitor-device-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-monitor-device images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-monitor-device pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-monitor-device-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-monitor-device:*"
|
||||
- "ghcr.io/uug-ai/hub-monitor-device@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-monitor-device
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-monitor-device
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-monitor-device images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-monitor-device.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-monitor-device-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-monitor-device images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-monitor-device pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-monitor-device
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-monitor-device:*"
|
||||
- "ghcr.io/uug-ai/hub-monitor-device@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-monitor-device's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-monitor-device
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,68 @@
|
||||
{{- /*
|
||||
hub-objecttracking images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-objecttracking.
|
||||
The signature itself is checked by hub-objecttracking-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-objecttracking-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-objecttracking images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# The standard image is hardened (from v1.0.11), but its `-gpu` image is not:
|
||||
# it is built outside the shared release workflow. This policy stays in Audit,
|
||||
# even when imageHardening.validationFailureAction is Enforce. Once the `-gpu`
|
||||
# image is hardened, use the same line as hub-api-hardened-images.yaml.
|
||||
validationFailureAction: Audit
|
||||
# Kyverno's default (Fail) would stop hub-objecttracking pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-objecttracking-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-objecttracking:*"
|
||||
- "ghcr.io/uug-ai/hub-objecttracking@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-objecttracking
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-objecttracking
|
||||
{{- end }}
|
||||
@@ -0,0 +1,57 @@
|
||||
{{- /*
|
||||
hub-objecttracking images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-objecttracking.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-objecttracking-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-objecttracking images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# hub-objecttracking releases are signed (from v1.0.10), but the GPU image
|
||||
# (<tag>-gpu, built by the repository's release-gpu-image.yml) is not, and this
|
||||
# policy matches every hub-objecttracking tag. It therefore stays in Audit even
|
||||
# when imageVerification.validationFailureAction is Enforce, until the GPU
|
||||
# image is signed too. Then use the same line as hub-api-signed-images.yaml.
|
||||
validationFailureAction: Audit
|
||||
# Kyverno's default (Fail) would stop hub-objecttracking pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-objecttracking
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-objecttracking:*"
|
||||
- "ghcr.io/uug-ai/hub-objecttracking@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-objecttracking's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-objecttracking
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-analysis images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-analysis.
|
||||
The signature itself is checked by hub-pipeline-analysis-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-analysis-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-analysis images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-analysis pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-analysis-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-analysis:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-analysis@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-analysis
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-analysis
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-analysis images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-analysis.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-analysis-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-analysis images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-analysis pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-analysis
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-analysis:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-analysis@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-analysis's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-analysis
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-counting images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-counting.
|
||||
The signature itself is checked by hub-pipeline-counting-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-counting-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-counting images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-counting pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-counting-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-counting:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-counting@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-counting
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-counting
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-counting images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-counting.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-counting-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-counting images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-counting pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-counting
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-counting:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-counting@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-counting's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-counting
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-dominantcolors images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-dominantcolors.
|
||||
The signature itself is checked by hub-pipeline-dominantcolors-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-dominantcolors-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-dominantcolors images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-dominantcolors pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-dominantcolors-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-dominantcolors:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-dominantcolors@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-dominantcolors
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-dominantcolors
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-dominantcolors images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-dominantcolors.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-dominantcolors-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-dominantcolors images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-dominantcolors pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-dominantcolors
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-dominantcolors:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-dominantcolors@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-dominantcolors's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-dominantcolors
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-event images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-event.
|
||||
The signature itself is checked by hub-pipeline-event-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-event-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-event images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-event pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-event-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-event:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-event@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-event
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-event
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-event images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-event.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-event-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-event images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-event pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-event
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-event:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-event@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-event's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-event
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-export images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-export.
|
||||
The signature itself is checked by hub-pipeline-export-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-export-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-export images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-export pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-export-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-export:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-export@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-export
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-export
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-export images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-export.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-export-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-export images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-export pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-export
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-export:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-export@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-export's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-export
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-monitor images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-monitor.
|
||||
The signature itself is checked by hub-pipeline-monitor-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-monitor-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-monitor images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-monitor pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-monitor-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-monitor:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-monitor@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-monitor
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-monitor
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-monitor images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-monitor.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-monitor-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-monitor images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-monitor pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-monitor
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-monitor:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-monitor@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-monitor's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-monitor
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-notification images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-notification.
|
||||
The signature itself is checked by hub-pipeline-notification-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-notification-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-notification images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-notification pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-notification-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-notification
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-notification
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-notification images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-notification.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-notification-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-notification images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-notification pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-notification
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-notification's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-notification
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-notification-test images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-notification-test.
|
||||
The signature itself is checked by hub-pipeline-notification-test-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-notification-test-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-notification-test images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-notification-test pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-notification-test-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification-test:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification-test@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-notification-test
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-notification-test
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-notification-test images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-notification-test.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-notification-test-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-notification-test images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-notification-test pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-notification-test
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification-test:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-notification-test@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-notification-test's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-notification-test
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-sequence images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-sequence.
|
||||
The signature itself is checked by hub-pipeline-sequence-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-sequence-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-sequence images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-sequence pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-sequence-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sequence:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sequence@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-sequence
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-sequence
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-sequence images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-sequence.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-sequence-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-sequence images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-sequence pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-sequence
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sequence:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sequence@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-sequence's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-sequence
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-sprite images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-sprite.
|
||||
The signature itself is checked by hub-pipeline-sprite-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-sprite-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-sprite images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-sprite pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-sprite-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sprite:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sprite@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-sprite
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-sprite
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-sprite images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-sprite.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-sprite-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-sprite images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-sprite pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-sprite
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sprite:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-sprite@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-sprite's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-sprite
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-throttler images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-throttler.
|
||||
The signature itself is checked by hub-pipeline-throttler-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-throttler-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-throttler images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-throttler pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-throttler-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-throttler:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-throttler@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-throttler
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-throttler
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-throttler images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-throttler.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-throttler-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-throttler images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-throttler pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-throttler
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-throttler:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-throttler@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-throttler's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-throttler
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-pipeline-thumbnail images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-pipeline-thumbnail.
|
||||
The signature itself is checked by hub-pipeline-thumbnail-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-thumbnail-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-thumbnail images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-thumbnail pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-thumbnail-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-thumbnail:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-thumbnail@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-thumbnail
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-pipeline-thumbnail
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-pipeline-thumbnail images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-pipeline-thumbnail.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-pipeline-thumbnail-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-pipeline-thumbnail images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-pipeline-thumbnail pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-pipeline-thumbnail
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-pipeline-thumbnail:*"
|
||||
- "ghcr.io/uug-ai/hub-pipeline-thumbnail@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-pipeline-thumbnail's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-pipeline-thumbnail
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-reactivatesubscriptions images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-reactivatesubscriptions.
|
||||
The signature itself is checked by hub-reactivatesubscriptions-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-reactivatesubscriptions-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-reactivatesubscriptions images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-reactivatesubscriptions pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-reactivatesubscriptions-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-reactivatesubscriptions:*"
|
||||
- "ghcr.io/uug-ai/hub-reactivatesubscriptions@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-reactivatesubscriptions
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-reactivatesubscriptions
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-reactivatesubscriptions images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-reactivatesubscriptions.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-reactivatesubscriptions-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-reactivatesubscriptions images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-reactivatesubscriptions pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-reactivatesubscriptions
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-reactivatesubscriptions:*"
|
||||
- "ghcr.io/uug-ai/hub-reactivatesubscriptions@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-reactivatesubscriptions's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-reactivatesubscriptions
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-vlm images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-vlm.
|
||||
The signature itself is checked by hub-vlm-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-vlm-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-vlm images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-vlm pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-vlm-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-vlm:*"
|
||||
- "ghcr.io/uug-ai/hub-vlm@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-vlm
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-vlm
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-vlm images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-vlm.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-vlm-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-vlm images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-vlm pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-vlm
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-vlm:*"
|
||||
- "ghcr.io/uug-ai/hub-vlm@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-vlm's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-vlm
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{- /*
|
||||
hub-workflows images must come from a hardened release: they carry the signed
|
||||
image-hardening attestation (result "passed") that the UUG.AI release workflow
|
||||
adds after all hardening gates pass, for uug-ai/hub-workflows.
|
||||
The signature itself is checked by hub-workflows-signed-images.yaml.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageHardening.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageHardening.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-workflows-hardened-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-workflows images must come from a hardened UUG.AI release
|
||||
policies.kyverno.io/category: Image hardening
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, attestation required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report images without a hardened release, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageHardening.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-workflows pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-workflows-hardened
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-workflows:*"
|
||||
- "ghcr.io/uug-ai/hub-workflows@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestations:
|
||||
- type: https://github.com/uug-ai/workflows/attestations/image-hardening/v1
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
githubWorkflowRepository: uug-ai/hub-workflows
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
# Fields of the attestation's predicate. {{`{{ ... }}`}} is Kyverno
|
||||
# syntax, escaped so Helm leaves it alone.
|
||||
conditions:
|
||||
- all:
|
||||
- key: "{{`{{ result }}`}}"
|
||||
operator: Equals
|
||||
value: passed
|
||||
- key: "{{`{{ repository }}`}}"
|
||||
operator: Equals
|
||||
value: uug-ai/hub-workflows
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
hub-workflows images must be signed by UUG.AI: a keyless cosign signature issued by
|
||||
GitHub Actions, made by the UUG.AI release workflow, for uug-ai/hub-workflows.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: hub-workflows-signed-images
|
||||
annotations:
|
||||
policies.kyverno.io/title: hub-workflows images must be signed by UUG.AI
|
||||
policies.kyverno.io/category: Image signing
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
# Kyverno defaults apply: background scans of running pods, signature required.
|
||||
# Only settings whose Kyverno default would change behaviour are set below.
|
||||
spec:
|
||||
# Audit: report unsigned images, don't block. Enforce: reject the pod.
|
||||
validationFailureAction: {{ .Values.imageVerification.validationFailureAction }}
|
||||
# Kyverno's default (Fail) would stop hub-workflows pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
# Verifying against GHCR and Rekor can exceed the 10s default.
|
||||
webhookTimeoutSeconds: 30
|
||||
rules:
|
||||
- name: verify-hub-workflows
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "ghcr.io/uug-ai/hub-workflows:*"
|
||||
- "ghcr.io/uug-ai/hub-workflows@*"
|
||||
# Kyverno's defaults (true) would rewrite pod images to digests and
|
||||
# report every tag-based image; enable together with Enforce.
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
attestors:
|
||||
- entries:
|
||||
- keyless:
|
||||
issuer: https://token.actions.githubusercontent.com
|
||||
# The UUG.AI release workflow, at a branch/tag ref or a commit.
|
||||
subjectRegExp: '^https://github\.com/uug-ai/workflows/\.github/workflows/release-create\.yml@(refs/.+|[0-9a-f]{40})$'
|
||||
additionalExtensions:
|
||||
# That workflow signs for every UUG.AI repository; this
|
||||
# binds the signature to hub-workflows's own repository.
|
||||
githubWorkflowRepository: uug-ai/hub-workflows
|
||||
rekor:
|
||||
url: https://rekor.sigstore.dev
|
||||
{{- end }}
|
||||
@@ -0,0 +1,54 @@
|
||||
{{- /*
|
||||
UUG.AI images are trusted only from ghcr.io/uug-ai: report a container, init
|
||||
container or ephemeral container image that is a UUG.AI image (uugai/... on
|
||||
Docker Hub, or any registry's uugai/ or uug-ai/ organisation) pulled from
|
||||
anywhere else. Other images in the namespace (agents, cert-manager solvers,
|
||||
third-party tools) are not the chart's to vouch for and are ignored. Signature
|
||||
and hardening are checked per image by the *-signed-images / *-hardened-images
|
||||
policies, which match ghcr.io/uug-ai images only.
|
||||
A namespaced Policy, so it applies only to the release namespace.
|
||||
Rendered only when imageVerification.enabled is true and Kyverno is installed.
|
||||
*/ -}}
|
||||
{{- if and .Values.imageVerification.enabled (.Capabilities.APIVersions.Has "kyverno.io/v1") }}
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: trusted-registry
|
||||
annotations:
|
||||
policies.kyverno.io/title: UUG.AI images must come from ghcr.io/uug-ai
|
||||
policies.kyverno.io/category: Image registry
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
spec:
|
||||
# Reports UUG.AI images from other registries without blocking them, even
|
||||
# when imageVerification.validationFailureAction is Enforce.
|
||||
validationFailureAction: Audit
|
||||
# Kyverno's default (Fail) would stop pods starting while Kyverno is down.
|
||||
failurePolicy: Ignore
|
||||
rules:
|
||||
- name: images-from-ghcr-uug-ai
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "UUG.AI images must come from the trusted registry ghcr.io/uug-ai/."
|
||||
foreach:
|
||||
- list: "request.object.spec.[containers, initContainers, ephemeralContainers][]"
|
||||
deny:
|
||||
conditions:
|
||||
all:
|
||||
# A UUG.AI image: Docker Hub uugai/..., or a uugai/ or uug-ai/
|
||||
# organisation on any registry ...
|
||||
- key: "{{`{{ element.image }}`}}"
|
||||
operator: AnyIn
|
||||
value:
|
||||
- "uugai/*"
|
||||
- "*/uugai/*"
|
||||
- "*/uug-ai/*"
|
||||
# ... that is not pulled from ghcr.io/uug-ai.
|
||||
- key: "{{`{{ element.image }}`}}"
|
||||
operator: NotEquals
|
||||
value: "ghcr.io/uug-ai/*"
|
||||
{{- end }}
|
||||
@@ -8,8 +8,91 @@
|
||||
"pattern": "^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"
|
||||
},
|
||||
"classificationCatalog": {
|
||||
"not": {},
|
||||
"description": "Removed in 0.155.0. Store the complete catalog in a ConfigMap and use workflowConfiguration.configMaps with replace: true at catalogs/classifications.json."
|
||||
"type": ["array", "null"],
|
||||
"minItems": 1,
|
||||
"description": "Optional inline classification catalog in the Hub shared choice catalog format; replaces the bundled defaults in the chart's classification-catalog ConfigMap. Omit (or null) for the bundled defaults. Keys must be unique (checked when rendering).",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["key", "label"],
|
||||
"properties": {
|
||||
"key": {"type": "string", "minLength": 1},
|
||||
"label": {"type": "string", "minLength": 1},
|
||||
"icon": {"type": "string", "minLength": 1}
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageVerification": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Kyverno policies (templates/kyverno/) requiring UUG.AI images to be signed by UUG.AI. Created only when the cluster serves kyverno.io/v1.",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Create the policies when Kyverno is installed."
|
||||
},
|
||||
"validationFailureAction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Audit",
|
||||
"Enforce"
|
||||
],
|
||||
"description": "Audit reports unsigned images but lets them run; Enforce rejects them."
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageHardening": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Kyverno policies (templates/kyverno/*-hardened-images.yaml) requiring images to come from a hardened UUG.AI release (signed image-hardening attestation). Created only when the cluster serves kyverno.io/v1.",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Create the hardening policies when Kyverno is installed."
|
||||
},
|
||||
"validationFailureAction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Audit",
|
||||
"Enforce"
|
||||
],
|
||||
"description": "Audit reports images without a hardened release but lets them run; Enforce rejects them."
|
||||
}
|
||||
}
|
||||
},
|
||||
"deviceTags": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"system": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Owners may assign system tags and global workflows may select devices by them. Only for deployments whose owners are trusted (self-hosted)."
|
||||
},
|
||||
"catalog": {
|
||||
"type": "array",
|
||||
"description": "The system tags owners can assign, in the Hub shared choice catalog format (key, label) plus an optional description. Keys must be unique (checked when rendering).",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["key", "label"],
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string",
|
||||
"maxLength": 64,
|
||||
"pattern": "^[a-z0-9]([a-z0-9._:-]*[a-z0-9])?$"
|
||||
},
|
||||
"label": {"type": "string", "minLength": 1},
|
||||
"description": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kerberoshub": {
|
||||
"type": "object",
|
||||
@@ -17,12 +100,67 @@
|
||||
"api": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mcp": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"allowedOrigins": {
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://[^/?#*@,\\s]+$"
|
||||
},
|
||||
"description": "Exact HTTP(S) origins for browser MCP clients, without wildcards, credentials, paths or trailing slashes. Independent of REST CORS."
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkeys": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"rpId": {
|
||||
"type": "string",
|
||||
"description": "Stable WebAuthn relying-party hostname, without scheme, port or path. Must match each frontend origin's hostname or be its parent domain."
|
||||
},
|
||||
"origins": {
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^https://[^/?#]+$|^http://localhost(:[0-9]+)?$"
|
||||
},
|
||||
"description": "Exact trusted frontend origins, with no path or trailing slash. HTTPS is required except for HTTP localhost development."
|
||||
},
|
||||
"rpName": {"type": "string"}
|
||||
},
|
||||
"if": {
|
||||
"required": ["enabled"],
|
||||
"properties": {"enabled": {"const": true}}
|
||||
},
|
||||
"then": {
|
||||
"required": ["rpId", "origins"],
|
||||
"properties": {
|
||||
"rpId": {"minLength": 1},
|
||||
"origins": {"minItems": 1}
|
||||
}
|
||||
}
|
||||
},
|
||||
"corsAllowedOrigins": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://[^/?#]+$"
|
||||
}
|
||||
},
|
||||
"auditExportMaxEventsPerFile": {
|
||||
"type": ["integer", "string"],
|
||||
"minimum": 1,
|
||||
"maximum": 1000000,
|
||||
"pattern": "^([1-9][0-9]{0,5}|1000000)?$",
|
||||
"description": "Most audit events one export file holds (AUDIT_EXPORT_MAX_EVENTS_PER_FILE). Empty uses the API default of 100000."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+319
-110
@@ -26,6 +26,28 @@ readOnly: false # Set to 'true' to halt all write operations to the database (e.
|
||||
# - ui: Hub services only
|
||||
mode: "all"
|
||||
###########################################################################
|
||||
# Image signature verification (Kyverno)
|
||||
###########################################################################
|
||||
# Kyverno policies in templates/kyverno/ (one file per ghcr.io/uug-ai image)
|
||||
# requiring UUG.AI images to be signed by UUG.AI. Opt-in: when enabled, they are
|
||||
# created only if Kyverno is installed.
|
||||
imageVerification:
|
||||
enabled: false
|
||||
# Audit: report unsigned images (PolicyReports) but let them run.
|
||||
# Enforce: reject pods whose image is unsigned or signed for another repository.
|
||||
# Images whose releases are not signed yet always stay in Audit (see README).
|
||||
validationFailureAction: Audit
|
||||
# Kyverno policies in templates/kyverno/ (*-hardened-images.yaml, one per image
|
||||
# whose repository makes hardened releases) requiring the image to come from a
|
||||
# hardened UUG.AI release: a signed image-hardening attestation with result
|
||||
# "passed" for the image's own repository. Opt-in and separate from
|
||||
# imageVerification, since only releases made with hardening enabled carry it.
|
||||
imageHardening:
|
||||
enabled: false
|
||||
# Audit: report images without a hardened release but let them run.
|
||||
# Enforce: reject pods whose image is not from a hardened release.
|
||||
validationFailureAction: Audit
|
||||
###########################################################################
|
||||
# Global configuration
|
||||
###########################################################################
|
||||
global:
|
||||
@@ -50,7 +72,6 @@ mongodb:
|
||||
# hub-pipeline-monitor, ...) instead of the one in uri, so the Atlas query
|
||||
# profiler and currentOp show which service issued an operation.
|
||||
appNamePerService: true
|
||||
|
||||
# Self-hosted mongodb, you could also use the uri property above.
|
||||
host: mongodb.mongodb
|
||||
adminDatabase: admin
|
||||
@@ -73,7 +94,6 @@ mongodb:
|
||||
caFileName: ""
|
||||
mountPath: "/etc/mongodb/tls"
|
||||
insecureSkipVerify: false
|
||||
|
||||
# Classifications supported by Hub filters, alerts, markers, and other
|
||||
# downstream processing. Classifier output keys must match these values.
|
||||
# Disable this to use the legacy classification catalog stored in MongoDB.
|
||||
@@ -82,9 +102,39 @@ classificationCatalogEnabled: true
|
||||
# When set, do not create a catalog ConfigMap; this replaces bundled defaults.
|
||||
classificationCatalogExistingConfigMap: ""
|
||||
# Defaults live in templates/configMaps/catalogs/classifications.yaml.
|
||||
# Inline classificationCatalog values are no longer accepted (including null/[]).
|
||||
# Use a ConfigMap item with path: catalogs/classifications.json and replace: true.
|
||||
# Optionally define the complete catalog inline instead; it replaces the
|
||||
# defaults in the chart's classification-catalog ConfigMap (and so the bundled
|
||||
# catalogs/classifications.json). Entries are {key, label, icon?} with unique
|
||||
# keys. Do not combine it with classificationCatalogExistingConfigMap or a
|
||||
# catalogs/classifications.json replacement in workflowConfiguration.
|
||||
# classificationCatalog:
|
||||
# - key: car
|
||||
# label: Car
|
||||
# icon: car
|
||||
|
||||
# Device tags, grouped by type. System tags are defined here and assigned by
|
||||
# owners (a multi-select on the device page); global workflows select devices
|
||||
# across organisations by system tag (`systemTags` in a trigger). Owners set
|
||||
# them, so any owner could enroll devices into such a workflow: enable only
|
||||
# where owners are the deployment's administrators (self-hosted), never on
|
||||
# multi-tenant SaaS. While disabled, hub-api gets an empty catalog (system tags
|
||||
# cannot be set) and rendering fails on workflows that select devices by
|
||||
# system tag.
|
||||
deviceTags:
|
||||
system:
|
||||
enabled: false # a boolean (true/false), not a string
|
||||
# The only system tags owners can assign, in the Hub shared choice catalog
|
||||
# format (as catalogs/classifications.json) plus an optional description.
|
||||
# Rendered into the device-system-tags ConfigMap for hub-api.
|
||||
# key stored tag: 1-64 characters of a-z, 0-9, ".", "_", ":" or
|
||||
# "-", starting and ending with a letter or digit; unique.
|
||||
# label display name.
|
||||
# description optional help text shown with the tag.
|
||||
# Workflow trigger systemTags must exist here; otherwise rendering fails.
|
||||
catalog: []
|
||||
# - key: anpr-pilot
|
||||
# label: ANPR pilot
|
||||
# description: Runs licence plate recognition on this camera
|
||||
# Configuration packaging only: consuming contracts requires a compatible
|
||||
# API/frontend. Enabling this mounts files but does not register stage workers.
|
||||
workflowConfiguration:
|
||||
@@ -97,7 +147,7 @@ workflowConfiguration:
|
||||
# Replacement requires includeDefaults: true and a known bundled destination path.
|
||||
# Unmarked collisions and repeated custom destinations are rejected.
|
||||
# Replacing catalogs/classifications.json also supplies the classification API:
|
||||
# do not combine it with classificationCatalogExistingConfigMap.
|
||||
# do not combine it with classificationCatalogExistingConfigMap or classificationCatalog.
|
||||
# Legacy existingConfigMap/items/extraConfigMaps remain supported, but cannot
|
||||
# be mixed with includeDefaults/configMaps. Both interfaces are omitted here
|
||||
# so Helm's default merging does not introduce a false mixed configuration.
|
||||
@@ -178,17 +228,27 @@ opentelemetry:
|
||||
# the collector terminates TLS. A scheme-less value defaults to TLS and
|
||||
# fails against a plaintext collector ("server gave HTTP response to HTTPS client").
|
||||
endpoint: "http://otel-collector:4318"
|
||||
# Trace sampling, passed to the services as OTEL_TRACES_SAMPLER and
|
||||
# OTEL_TRACES_SAMPLER_ARG. Leave empty to keep the SDK default, which records
|
||||
# every trace. Example: keep ~10% of traces, and follow the parent's decision
|
||||
# for spans that continue an upstream trace:
|
||||
# type: "parentbased_traceidratio"
|
||||
# arg: "0.1"
|
||||
# Supported types: always_on, always_off, traceidratio, parentbased_always_on,
|
||||
# parentbased_always_off, parentbased_traceidratio.
|
||||
sampler:
|
||||
type: ""
|
||||
arg: ""
|
||||
# Trace sampling is decided where a trace starts:
|
||||
# - Uploads start at the Vault, whose deployment sets their rate
|
||||
# (TRACE_SAMPLER_RATIO_UPLOAD / TRACE_SAMPLER_RATIO_OTHER).
|
||||
# - hub-api starts its own traces; apiSamplingRatios below sets its rates.
|
||||
# hub-workflows, the pipe-* services and the workflow stages only continue
|
||||
# traces started elsewhere: they follow that decision and never start traces
|
||||
# of their own (OTEL_TRACES_SAMPLER=parentbased_always_off, not configurable).
|
||||
#
|
||||
# apiSamplingRatios: hub-api's sampling ratio (0 to 1) per kind of work,
|
||||
# rendered as TRACE_SAMPLER_RATIO_<CLASS> (hub-api on trace library v1.2.6+).
|
||||
# Empty values are not rendered; with none set, hub-api records every trace.
|
||||
# operator: requests from users and API clients (UI, API tokens).
|
||||
# other: everything else hub-api starts: device heartbeats, agent uploads
|
||||
# and live segments, background work, queries outside a request.
|
||||
# Unset with operator set: records everything.
|
||||
# Example: ~10% of user requests, 1% of everything else:
|
||||
# operator: "0.1"
|
||||
# other: "0.01"
|
||||
apiSamplingRatios:
|
||||
operator: ""
|
||||
other: ""
|
||||
############################################
|
||||
# OpenAI configuration (semantic search)
|
||||
#
|
||||
@@ -226,9 +286,34 @@ kerberosvault:
|
||||
# For now it's used to create, edit users for Hub.
|
||||
###########################################################################
|
||||
admin:
|
||||
repository: uugai/admin
|
||||
# Signed release from the UUG.AI release workflow (only ghcr.io/uug-ai is trusted).
|
||||
# It runs shell-free as 65532:65532 on 8080 with a read-only root filesystem:
|
||||
# keep the runtime settings below together with the image (see README).
|
||||
repository: ghcr.io/uug-ai/admin
|
||||
containerPort: 8080
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.0"
|
||||
tag: "v1.4.6"
|
||||
replicas: 2
|
||||
# Optional pod topology spread constraints for this deployment. Empty by
|
||||
# default. Example:
|
||||
@@ -240,13 +325,16 @@ admin:
|
||||
# matchLabels:
|
||||
# app: admin
|
||||
topologySpreadConstraints: []
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
#volumes:
|
||||
# - name: extra
|
||||
# emptyDir: {}
|
||||
#volumeMounts:
|
||||
# - name: extra
|
||||
# mountPath: /data
|
||||
# The only writable path: memory-backed /tmp (counts against the pod memory
|
||||
# limit). Append extra volumes / volumeMounts to these lists.
|
||||
volumes:
|
||||
- name: admin-tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 16Mi
|
||||
volumeMounts:
|
||||
- name: admin-tmp
|
||||
mountPath: /tmp
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
resources:
|
||||
requests:
|
||||
@@ -293,8 +381,27 @@ kerberoshub:
|
||||
api:
|
||||
repository: ghcr.io/uug-ai/hub-api
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.9.51"
|
||||
tag: "v1.11.42"
|
||||
replicas: 2
|
||||
podSecurityContext:
|
||||
fsGroup: 65532
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
# Keep writable scratch space for attachment uploads and multipart parsing.
|
||||
volumes:
|
||||
- name: hub-api-tmp
|
||||
emptyDir: {}
|
||||
volumeMounts:
|
||||
- name: hub-api-tmp
|
||||
mountPath: /tmp
|
||||
audit:
|
||||
enabled: true
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
@@ -303,11 +410,22 @@ kerberoshub:
|
||||
serviceEnabled: true
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
jwtSecret: "this-is-a-secret-please-change-to-random-string" # change to a random value, this is for generating JWT tokens.
|
||||
# How long a user stays signed in (Go durations, e.g. "15m", "12h").
|
||||
session:
|
||||
accessTokenTimeout: "15m" # Lifetime of one access token; the frontend renews it silently.
|
||||
idleTimeout: "12h" # A session that is not used for this long ends.
|
||||
maxLifetime: "24h" # Hard limit counted from login; the user must sign in again after it.
|
||||
schema: "https"
|
||||
url: "api.yourdomain.com"
|
||||
# Additional complete HTTP(S) origins allowed to call the Hub API.
|
||||
# The configured frontend origins remain allowed automatically.
|
||||
corsAllowedOrigins: []
|
||||
# Read-only Streamable HTTP MCP endpoint at /mcp; requires a compatible API image.
|
||||
mcp:
|
||||
enabled: false
|
||||
# Exact HTTP(S) origins for browser MCP clients; no wildcards or trailing slash.
|
||||
# Clients without an Origin header (such as VS Code) need no entries.
|
||||
allowedOrigins: []
|
||||
# Temporarily stop serving the polled GET /devices list: hub-api answers 204
|
||||
# without querying MongoDB. The frontend still loads devices once through
|
||||
# /session/bootstrap, but device online/offline status stops refreshing.
|
||||
@@ -329,6 +447,7 @@ kerberoshub:
|
||||
memory: 100Mi
|
||||
cpu: 250m
|
||||
# E-mail templates
|
||||
# Append custom mounts/volumes to the lists above; retain hub-api-tmp.
|
||||
#volumeMounts:
|
||||
# - name: custom-email-templates
|
||||
# mountPath: /mail
|
||||
@@ -351,6 +470,13 @@ kerberoshub:
|
||||
|
||||
# MFA issuer name
|
||||
mfaIssuer: "yourdomain.com"
|
||||
# WebAuthn passkeys for users and sub-users; requires compatible API/frontend images.
|
||||
# Use the public frontend hostname/origins, not the API URL. Keep rpId stable.
|
||||
passkeys:
|
||||
enabled: false
|
||||
rpId: "" # e.g. "hub.example.com", without scheme, port or path.
|
||||
origins: [] # e.g. ["https://hub.example.com"]; exact origins, no trailing slash.
|
||||
rpName: "Kerberos Hub"
|
||||
# Admin API's are made available for automation of Kerberos Hub.
|
||||
# To access those API's (e.g. creation of owner users), an API key needs to be provided.
|
||||
apiKey: "a-random-admin-api-key"
|
||||
@@ -366,6 +492,11 @@ kerberoshub:
|
||||
# beyond this cap, the value is clamped down to `now + casesMaxRetentionDays`.
|
||||
# Set to "0" (or a negative value) to disable the cap (no maximum).
|
||||
casesMaxRetentionDays: "0"
|
||||
# Most audit events one export file holds (AUDIT_EXPORT_MAX_EVENTS_PER_FILE).
|
||||
# It does not refuse larger exports: the Audit page downloads them as
|
||||
# several files of at most this size. An integer from 1 to 1000000; leave
|
||||
# empty to use the API default of 100000.
|
||||
auditExportMaxEventsPerFile: ""
|
||||
## Certificates
|
||||
tls:
|
||||
- hosts:
|
||||
@@ -424,8 +555,28 @@ kerberoshub:
|
||||
frontend:
|
||||
repository: ghcr.io/uug-ai/hub-frontend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.13.9"
|
||||
tag: "v1.19.35"
|
||||
replicas: 2
|
||||
containerPort: 8080
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
# Keep these entries when adding custom branding/translation mounts.
|
||||
volumes:
|
||||
- name: frontend-tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 16Mi
|
||||
volumeMounts:
|
||||
- name: frontend-tmp
|
||||
mountPath: /tmp
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Set to false to skip rendering the hub-frontend Service (e.g. when an
|
||||
# external/shared Service is managed elsewhere).
|
||||
@@ -560,6 +711,7 @@ kerberoshub:
|
||||
switcherEnabled: "false" # Enable or disable organisation switching 'true' or 'false'
|
||||
creationEnabled: "false" # Enable or disable organisation creation; requires switcherEnabled 'true' or 'false'
|
||||
settingsEnabled: "false" # Enable or disable the organisation settings link 'true' or 'false'
|
||||
membersAccessPreviewEnabled: "false" # Show the mocked "Users (preview)" tab in organisation settings to owners 'true' or 'false'
|
||||
projects:
|
||||
enabled: "" # Fallback project group switch used only when organisations.enabled is empty
|
||||
switcherEnabled: "false" # Enable or disable the read-only project dropdown 'true' or 'false'
|
||||
@@ -599,6 +751,13 @@ kerberoshub:
|
||||
sitesFullscreenEnabled: "true" # Enable or disable the fullscreen Sites map 'true' or 'false'
|
||||
# Media page
|
||||
media:
|
||||
# Bulk "Forward media" action in the Recordings Actions menu (on-demand forwarding of metadata-only recordings).
|
||||
forward:
|
||||
enabled: "true" # Enable or disable the Forward media action in media 'true' or 'false'
|
||||
# Analysis block (dominant colors, thumbnail, sprite, motion) on the media detail page.
|
||||
detail:
|
||||
analysis:
|
||||
enabled: "true" # Enable or disable the Analysis block on the media detail page 'true' or 'false'
|
||||
filter:
|
||||
date:
|
||||
enabled: "true" # Enable or disable date filter in media 'true' or 'false'
|
||||
@@ -678,6 +837,7 @@ kerberoshub:
|
||||
publicKey: ""
|
||||
googlemaps: # Google maps is used inside the application to visualise cameras and sites.
|
||||
apikey: "xxxx"
|
||||
placesApi: "legacy" # Places API for address autocomplete: "legacy" (default) or "new" for keys with Places API (New) enabled. Uses the same apikey.
|
||||
zendesk: # We can use different support tools, for now we use Zendesk but others can be integrated
|
||||
url: "yourdomain.zendesk.com"
|
||||
posthog: # Posthog is used for auditing and user interaction logging
|
||||
@@ -702,9 +862,12 @@ kerberoshub:
|
||||
organization: "github-organization"
|
||||
team: "github-team"
|
||||
cleanup:
|
||||
# Explicit opt-in for a selected hardened image; legacy defaults are unchanged.
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-cleanup
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.4.19"
|
||||
tag: "v1.4.27"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -752,13 +915,19 @@ kerberoshub:
|
||||
requests:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
# Dispatches canonical audit_events to one or more external webhook sinks.
|
||||
# Credentials are always read from existing Secrets and never stored here.
|
||||
# Dispatches canonical audit_events to one or more destinations: webhook
|
||||
# sinks, or S3 Object Lock buckets for immutable storage.
|
||||
# Destination credentials are set inline on each destination.
|
||||
audit:
|
||||
repository: ghcr.io/uug-ai/hub-audit
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.0.1"
|
||||
tag: "v1.0.12"
|
||||
replicas: 1
|
||||
resources: {}
|
||||
# resources:
|
||||
# requests:
|
||||
# memory: 32Mi
|
||||
# cpu: 10m
|
||||
dispatchInterval: "5s"
|
||||
leaseDuration: "2m"
|
||||
terminationGracePeriodSeconds: 150 # Keep above leaseDuration so an in-flight cycle can finish.
|
||||
@@ -766,37 +935,70 @@ kerberoshub:
|
||||
volumes: []
|
||||
volumeMounts: []
|
||||
extraEnv: []
|
||||
# Optional ServiceAccount for hub-audit alone, for example to grant S3 access
|
||||
# through IRSA without giving it to every Hub workload. When create is false
|
||||
# and name is set, that existing ServiceAccount is used; otherwise the pod
|
||||
# falls back to kerberoshub.serviceAccount.
|
||||
serviceAccount:
|
||||
create: false
|
||||
name: ""
|
||||
annotations: {}
|
||||
# eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/hub-audit-archive
|
||||
labels: {}
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
interval: 15s
|
||||
# Each destination is optional; see the README for every field. Webhook:
|
||||
destinations: []
|
||||
# - id: primary-siem
|
||||
# type: webhook
|
||||
# enabled: true
|
||||
# url: https://siem.example.com/api/audit
|
||||
# timeoutSeconds: 10
|
||||
# batchSize: 100
|
||||
# maxAttempts: 10
|
||||
# startAt: latest # latest | beginning, applied only on first creation
|
||||
# headers:
|
||||
# - id: primary-siem # required; ^[a-z][a-z0-9-]{0,62}$, keeps the checkpoint
|
||||
# type: webhook # optional: webhook (default) | s3
|
||||
# enabled: true # optional, default true; false pauses delivery
|
||||
# url: https://siem.example.com/api/audit # required, http or https
|
||||
# timeoutSeconds: 10 # optional, default 10, at most 60
|
||||
# batchSize: 100 # optional, default 100, at most 1000
|
||||
# maxAttempts: 10 # optional, default 10; then the batch is dead-lettered
|
||||
# startAt: latest # optional: latest (default) | beginning, for a new id only
|
||||
# headers: # optional; not Authorization or Idempotency-Key
|
||||
# X-Source: kerberos-hub
|
||||
# bearerTokenSecret:
|
||||
# name: audit-primary-siem
|
||||
# key: token
|
||||
# # Optional inline credentials. The chart stores them in Secret
|
||||
# # hub-audit-<id>-credentials and mounts them.
|
||||
# bearerToken: "xxx" # sent as Authorization: Bearer <token>
|
||||
# secretHeaders:
|
||||
# X-Api-Key:
|
||||
# secretName: audit-primary-siem
|
||||
# secretKey: api-key
|
||||
# filters:
|
||||
# value: "xxx"
|
||||
# filters: # optional, default all events; an event must match every list set
|
||||
# organisationIds: []
|
||||
# projectIds: []
|
||||
# actions: []
|
||||
# categories: []
|
||||
# outcomes: [] # success | failure
|
||||
# resources:
|
||||
# requests:
|
||||
# memory: 32Mi
|
||||
# cpu: 10m
|
||||
# S3 Object Lock destination. The bucket needs versioning, Object Lock and a
|
||||
# COMPLIANCE default retention; hub-audit refuses to deliver otherwise. Each
|
||||
# batch is written as <prefix>/<id>/yyyy/mm/dd/<firstId>-<lastId>.ndjson.gz.
|
||||
# Per-provider region/endpoint values (AWS, Wasabi, B2, Ceph RGW, MinIO, Garage):
|
||||
# https://learn.uug.ai/docs/hub/audit-events/#s3-providers
|
||||
# - id: immutable-archive # required
|
||||
# type: s3 # required for S3
|
||||
# enabled: true # optional, default true
|
||||
# timeoutSeconds: 30
|
||||
# batchSize: 500
|
||||
# maxAttempts: 100 # keep high: exhausted batches are dead-lettered, not archived
|
||||
# startAt: beginning
|
||||
# s3:
|
||||
# bucket: hub-audit-archive # required
|
||||
# region: eu-west-1 # required, also for S3-compatible stores
|
||||
# prefix: hub # optional, default none
|
||||
# endpoint: https://s3.example.com # optional; S3-compatible stores only, omit for AWS S3
|
||||
# forcePathStyle: true # optional, default false; usually true for Ceph RGW, MinIO and Garage
|
||||
# # Optional, default false. Only for stores without Object Lock (e.g. Garage):
|
||||
# # skips the lock check, so archived batches are deletable.
|
||||
# allowUnlockedBucket: false
|
||||
# # Optional inline credentials, both or neither. The chart stores them
|
||||
# # in Secret hub-audit-<id>-credentials and mounts them.
|
||||
# accessKey: "xxx"
|
||||
# secretKey: "xxx"
|
||||
# # Without them, hub-audit uses the pod's AWS identity (IRSA via
|
||||
# # kerberoshub.audit.serviceAccount, or an instance profile): AWS S3 only.
|
||||
# hub-workflows is the standalone, queue-driven workflow engine. It consumes
|
||||
# pipeline events and dispatches the stages declared in its workflow
|
||||
# definitions, tracking each run in its own `workflow_runs` collection. It shares events
|
||||
@@ -839,7 +1041,9 @@ kerberoshub:
|
||||
# triggers how a run OPENS. Omit for a single bare automatic trigger
|
||||
# (opens for every recording); the per-stage `needs` then decide
|
||||
# which stages FIRE. Narrow with device/schedule triggers, e.g.
|
||||
# `- {type: automatic, devices: [{key: <device-key>}]}`.
|
||||
# `- {type: automatic, devices: [{key: <device-key>}]}`, or by
|
||||
# device label across organisations, e.g.
|
||||
# `- {type: automatic, systemTags: [anpr-pilot]}` (see deviceTags).
|
||||
# stages the executable stages, each {operation, dispatch?, needs?,
|
||||
# needsMode?}. dispatch is "always" (default) or "conditional";
|
||||
# a conditional stage's `needs` are upstream dependencies, each
|
||||
@@ -913,8 +1117,10 @@ kerberoshub:
|
||||
# `enabled` here.
|
||||
workflows:
|
||||
repository: ghcr.io/uug-ai/hub-workflows
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.0.0"
|
||||
tag: "v1.0.49"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -944,7 +1150,7 @@ kerberoshub:
|
||||
# enabled: true
|
||||
# repository: ghcr.io/uug-ai/hub-loitering
|
||||
# pullPolicy: IfNotPresent
|
||||
# tag: "v1.0.0"
|
||||
# tag: "v1.0.11"
|
||||
# replicas: 1 # Number of pods for the worker.
|
||||
# topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# #volumes:
|
||||
@@ -973,7 +1179,7 @@ kerberoshub:
|
||||
# enabled: true
|
||||
# repository: ghcr.io/uug-ai/hub-objecttracking
|
||||
# pullPolicy: IfNotPresent
|
||||
# tag: "v1.0.0"
|
||||
# tag: "v1.0.11"
|
||||
# replicas: 1 # Number of pods for the worker.
|
||||
# topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
@@ -998,7 +1204,7 @@ kerberoshub:
|
||||
# enabled: true
|
||||
# repository: ghcr.io/uug-ai/hub-vlm
|
||||
# pullPolicy: IfNotPresent
|
||||
# tag: "v1.0.0"
|
||||
# tag: "v1.0.9"
|
||||
# replicas: 1 # Number of pods for the worker.
|
||||
# topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
@@ -1021,12 +1227,19 @@ kerberoshub:
|
||||
# memory: 128Mi
|
||||
# cpu: 100m
|
||||
monitordevice:
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-monitor-device
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.4.2"
|
||||
tag: "v1.4.15"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
# Seconds between device status scans. Sets how quickly a camera going
|
||||
# offline/online is detected. With "Group notifications" on, hub-monitor-device
|
||||
# v1.4.10+ holds a change 20 seconds (DEVICE_GROUPING_HOLD_SECONDS) to collect
|
||||
# other cameras that change at the same time; older releases hold one scan.
|
||||
scanIntervalSeconds: 60
|
||||
resources:
|
||||
requests:
|
||||
memory: 10Mi
|
||||
@@ -1040,9 +1253,9 @@ kerberoshub:
|
||||
# persistentVolumeClaim:
|
||||
# claimName: custom-layout-claim
|
||||
reactivate:
|
||||
repository: uugai/hub-reactivatesubscriptions
|
||||
repository: ghcr.io/uug-ai/hub-reactivatesubscriptions
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.0.2"
|
||||
tag: "v1.0.3"
|
||||
replicas: 0 # Number of pods for the service. Set to 0 to disable.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1057,43 +1270,6 @@ kerberoshub:
|
||||
requests:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
forwarder:
|
||||
enabled: false
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
#volumes:
|
||||
# - name: extra
|
||||
# emptyDir: {}
|
||||
#volumeMounts:
|
||||
# - name: extra
|
||||
# mountPath: /data
|
||||
#repository: kerberos/vault-forwarder
|
||||
#pullPolicy: IfNotPresent
|
||||
#tag: "1.0.2732389692"
|
||||
#resources:
|
||||
# requests:
|
||||
# memory: 10Mi
|
||||
# cpu: 10m
|
||||
# This proxy is legacy for the old agent, will be migrated in the new Hub API.
|
||||
proxy:
|
||||
enabled: false
|
||||
repository: uugai/hub-proxy
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.0.0"
|
||||
replicas: 0 # Number of pods for the service when enabled.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
#volumes:
|
||||
# - name: extra
|
||||
# emptyDir: {}
|
||||
#volumeMounts:
|
||||
# - name: extra
|
||||
# mountPath: /data
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
resources:
|
||||
requests:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
# The Kerberos Hub pipeline is a series of microservices that process the recordings.
|
||||
# Each microservice is responsible for a specific task, like counting objects, generating thumbnails, etc.
|
||||
# The pipeline is orchestrated through Kafka topics or RabbitMQ queues.
|
||||
@@ -1106,7 +1282,7 @@ kerberospipeline:
|
||||
# argocd.argoproj.io/sync-wave: "10"
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-event
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.1"
|
||||
tag: "v1.3.11"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1127,7 +1303,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "70"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.13"
|
||||
tag: "v1.3.30"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1148,7 +1324,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "60"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.6.26"
|
||||
tag: "v1.7.15"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1158,17 +1334,20 @@ kerberospipeline:
|
||||
#volumeMounts:
|
||||
# - name: extra
|
||||
# mountPath: /data
|
||||
logLevel: "info" # possible values: debug, info, warn, error
|
||||
resources:
|
||||
requests:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
throttler:
|
||||
repository: uugai/hub-pipeline-throttler
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-throttler
|
||||
deploymentAnnotations: {}
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "30"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.2.1"
|
||||
tag: "v1.2.11"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1184,12 +1363,14 @@ kerberospipeline:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
notify:
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-notification
|
||||
deploymentAnnotations: {}
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "20"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.18"
|
||||
tag: "v1.3.49"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
audit:
|
||||
enabled: true
|
||||
@@ -1209,9 +1390,9 @@ kerberospipeline:
|
||||
# persistentVolumeClaim:
|
||||
# claimName: custom-layout-claim
|
||||
notifyTest:
|
||||
repository: uugai/hub-pipeline-notification-test
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-notification-test
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.2.2"
|
||||
tag: "v1.2.8"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
resources:
|
||||
@@ -1232,7 +1413,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "40"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.8.22"
|
||||
tag: "v1.8.31"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1243,6 +1424,16 @@ kerberospipeline:
|
||||
# - name: extra
|
||||
# mountPath: /data
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
# Opt-in: after classification, re-enqueue the recording on the thumbnail
|
||||
# queue to regenerate its thumbnail from the first frame of a tracked moving
|
||||
# object (THUMBNAIL_REGENERATION_ENABLED). Adds up to one thumbnail job per
|
||||
# classified recording; size pipe-thumbnail accordingly before enabling.
|
||||
# minSeconds (THUMBNAIL_REGENERATION_MIN_SECONDS): only regenerate when the
|
||||
# object first appears at least this many seconds into the recording; earlier
|
||||
# objects are already in the original thumbnail. 0 regenerates for every object.
|
||||
thumbnailRegeneration:
|
||||
enabled: false
|
||||
minSeconds: 3
|
||||
# In-memory cache for hot-path MongoDB lookups (site vault per device).
|
||||
# Site changes apply after at most one TTL; each replica caches separately.
|
||||
dbCache:
|
||||
@@ -1253,6 +1444,8 @@ kerberospipeline:
|
||||
memory: 10Mi
|
||||
cpu: 10m
|
||||
dominantColor:
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
# Opt-in: deploys pipe-dominantcolor and tells the analysis stage to schedule
|
||||
# it (DOMINANTCOLOR_ENABLED). Requires an analysis image that reads the flag;
|
||||
# older images always publish to the dominantcolor queue.
|
||||
@@ -1262,7 +1455,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v2.0.3"
|
||||
tag: "v2.0.11"
|
||||
replicas: 3 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1281,12 +1474,14 @@ kerberospipeline:
|
||||
memory: 2Gi
|
||||
cpu: 1000m
|
||||
thumbnail:
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-thumbnail
|
||||
deploymentAnnotations: {}
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.15"
|
||||
tag: "v1.3.25"
|
||||
replicas: 2 # Number of pods for the service.
|
||||
prefetchCount: 0 # Max unacknowledged RabbitMQ messages per pod; 0 = service default (5).
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
@@ -1301,6 +1496,7 @@ kerberospipeline:
|
||||
quality: "1" # 1 (best) - 31 (worst)
|
||||
width: "600"
|
||||
height: "-1"
|
||||
skipNonKeyframes: true # Decode keyframes only for faster extraction; disable when exact-frame output is required.
|
||||
kerberosvault:
|
||||
enabled: true # If you want to use Kerberos Vault to store the thumbnails
|
||||
resources:
|
||||
@@ -1311,12 +1507,14 @@ kerberospipeline:
|
||||
memory: 2Gi
|
||||
cpu: 1000m
|
||||
counting:
|
||||
repository: uugai/hub-pipeline-counting
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-counting
|
||||
deploymentAnnotations: {}
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v2.0.0"
|
||||
tag: "v2.0.7"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1338,7 +1536,7 @@ kerberospipeline:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-sprite
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.1.21"
|
||||
tag: "v1.1.29"
|
||||
replicas: 5 # Number of pods for the service.
|
||||
prefetchCount: 0 # Max unacknowledged RabbitMQ messages per pod; 0 = service default (5).
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
@@ -1365,7 +1563,7 @@ kerberospipeline:
|
||||
export:
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-export
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.2.10"
|
||||
tag: "v1.2.23"
|
||||
replicas: 2 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
@@ -1418,5 +1616,16 @@ email:
|
||||
disabled: "disable"
|
||||
highupload: "highupload"
|
||||
device: "device"
|
||||
# Sent instead of "device" when several cameras of an account change status
|
||||
# in the same scan and the account groups device notifications.
|
||||
deviceGroup: "device_group"
|
||||
alertTitle: "[Alert] Kerberos Hub detected something an event"
|
||||
deviceTitle: "[Device] A Kerberos Agent's status has been changed"
|
||||
deviceGroupTitle: "[Device] Several cameras changed status"
|
||||
# Recording check alerts (Alerts → Devices → Recording check). Empty uses
|
||||
# the "recording" template with SMTP. For SendGrid or Mailgun, set the
|
||||
# template id; empty uses the device template there.
|
||||
recording: ""
|
||||
# Empty uses "[Device] A camera stopped recording", "[Device] A camera is
|
||||
# recording again" and their forms for several cameras.
|
||||
recordingTitle: ""
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
resource() {
|
||||
local source="$1"
|
||||
awk -v source="# Source: hub/templates/admin/$source.yaml" '
|
||||
/^---/ { selected=0 }
|
||||
/^# Source:/ { selected=($0 == source); next }
|
||||
selected { print }
|
||||
'
|
||||
}
|
||||
|
||||
assert_contains() {
|
||||
local rendered="$1" pattern="$2"
|
||||
if ! grep -Eq -- "$pattern" <<< "$rendered"; then
|
||||
printf 'Missing expected Admin setting: %s\n' "$pattern" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_absent() {
|
||||
local rendered="$1" pattern="$2"
|
||||
if grep -Eq -- "$pattern" <<< "$rendered"; then
|
||||
printf 'Unexpected Admin setting: %s\n' "$pattern" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Since chart 0.184.0 the hardened ghcr.io/uug-ai/admin runtime is the default;
|
||||
# LEGACY_FLAGS opts back into a legacy image on port 80.
|
||||
LEGACY_FLAGS=(
|
||||
--set admin.repository=uugai/admin
|
||||
--set admin.tag=v1.3.0
|
||||
--set admin.containerPort=80
|
||||
--set admin.securityContext=null
|
||||
--set admin.readinessProbe=null
|
||||
--set admin.livenessProbe=null
|
||||
--set admin.volumes=null
|
||||
--set admin.volumeMounts=null
|
||||
)
|
||||
|
||||
for mode in all ui; do
|
||||
hardened_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true)"
|
||||
hardened_deployment="$(resource deployment <<< "$hardened_render")"
|
||||
hardened_service="$(resource service <<< "$hardened_render")"
|
||||
hardened_ingress="$(resource ingress <<< "$hardened_render")"
|
||||
hardened_oauth="$(resource oauth2-proxy <<< "$hardened_render")"
|
||||
assert_contains "$hardened_deployment" 'image: "ghcr.io/uug-ai/admin:'
|
||||
assert_contains "$hardened_deployment" 'containerPort: 8080$'
|
||||
assert_absent "$hardened_deployment" 'containerPort: 80$'
|
||||
for setting in 'runAsNonRoot: true' 'runAsUser: 65532' 'runAsGroup: 65532' \
|
||||
'readOnlyRootFilesystem: true' 'allowPrivilegeEscalation: false' \
|
||||
'type: RuntimeDefault' 'drop:' '- ALL' 'medium: Memory' \
|
||||
'sizeLimit: 16Mi' 'mountPath: /tmp' 'name: admin-tmp'; do
|
||||
assert_contains "$hardened_deployment" "^[[:space:]]*(- )?$setting$"
|
||||
done
|
||||
for probe in readinessProbe livenessProbe; do
|
||||
probe_render="$(awk -v probe="$probe:" '
|
||||
/^ [a-zA-Z]/ { selected=($1 == probe) }
|
||||
selected { print }
|
||||
' <<< "$hardened_deployment")"
|
||||
assert_contains "$probe_render" 'path: /healthz$'
|
||||
assert_contains "$probe_render" 'port: http$'
|
||||
done
|
||||
assert_contains "$hardened_service" 'port: 80$'
|
||||
assert_contains "$hardened_service" 'targetPort: http$'
|
||||
|
||||
legacy_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true "${LEGACY_FLAGS[@]}")"
|
||||
legacy_deployment="$(resource deployment <<< "$legacy_render")"
|
||||
assert_contains "$legacy_deployment" 'containerPort: 80$'
|
||||
assert_absent "$legacy_deployment" 'securityContext:|readinessProbe:|livenessProbe:|admin-tmp'
|
||||
|
||||
[[ "$(resource service <<< "$legacy_render")" == "$hardened_service" ]]
|
||||
[[ "$(resource ingress <<< "$legacy_render")" == "$hardened_ingress" ]]
|
||||
[[ "$(resource oauth2-proxy <<< "$legacy_render")" == "$hardened_oauth" ]]
|
||||
assert_contains "$hardened_ingress" 'nginx.ingress.kubernetes.io/auth-url:'
|
||||
assert_contains "$hardened_ingress" 'number: 80$'
|
||||
|
||||
echo "OK ($mode): hardened ghcr.io defaults; legacy opt-out; stable Service, ingress and OAuth2"
|
||||
done
|
||||
|
||||
pipeline_render="$(helm template hub "$CHART_DIR" --set mode=pipeline)"
|
||||
assert_absent "$pipeline_render" '^# Source: hub/templates/admin/'
|
||||
|
||||
echo "All Admin runtime checks passed."
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
values=()
|
||||
if [[ $# -ge 2 ]]; then values=(--values "$2"); fi
|
||||
|
||||
resource() {
|
||||
local kind="$1" name="$2"
|
||||
awk -v kind="$kind" -v name="$name" '
|
||||
function emit() { if (matchedKind && matchedName) printf "%s", block }
|
||||
/^---$/ { emit(); block=""; matchedKind=0; matchedName=0 }
|
||||
{ block=block $0 "\n" }
|
||||
$0 == "kind: " kind { matchedKind=1 }
|
||||
$0 == " name: " name { matchedName=1 }
|
||||
END { emit() }
|
||||
'
|
||||
}
|
||||
|
||||
assert_contains() {
|
||||
if ! grep -Eq -- "$2" <<< "$1"; then
|
||||
printf 'Missing expected frontend setting: %s\n' "$2" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
for mode in all ui; do
|
||||
rendered="$(helm template hub "$CHART_DIR" "${values[@]}" --set "mode=$mode" \
|
||||
--set kerberoshub.frontend.demoEnabled=true)"
|
||||
for name in hub-frontend hub-frontend-demo; do
|
||||
deployment="$(resource Deployment "$name" <<< "$rendered")"
|
||||
assert_contains "$deployment" 'image: "ghcr.io/uug-ai/hub-frontend:v1.19.35"$'
|
||||
assert_contains "$deployment" 'containerPort: 8080$'
|
||||
[[ "$(grep -c 'containerPort:' <<< "$deployment")" == 1 ]]
|
||||
for setting in 'name: http' 'runAsNonRoot: true' 'runAsUser: 65532' \
|
||||
'runAsGroup: 65532' 'readOnlyRootFilesystem: true' \
|
||||
'allowPrivilegeEscalation: false' 'type: RuntimeDefault' 'drop:' '- ALL' \
|
||||
'medium: Memory' 'sizeLimit: 16Mi' 'mountPath: /tmp' 'name: frontend-tmp'; do
|
||||
assert_contains "$deployment" "^[[:space:]]*(- )?$setting$"
|
||||
done
|
||||
service="$(resource Service "$name-svc" <<< "$rendered")"
|
||||
assert_contains "$service" 'port: 80$'
|
||||
assert_contains "$service" 'targetPort: http$'
|
||||
echo "OK ($mode): $name hardened image, security, scratch and named routing"
|
||||
done
|
||||
admin="$(resource Deployment admin <<< "$rendered")"
|
||||
assert_contains "$admin" 'containerPort: 8080$'
|
||||
|
||||
legacy="$(helm template hub "$CHART_DIR" "${values[@]}" --set "mode=$mode" \
|
||||
--set kerberoshub.frontend.demoEnabled=true \
|
||||
--set kerberoshub.frontend.tag=v1.13.9 \
|
||||
--set kerberoshub.frontend.containerPort=80 \
|
||||
--set kerberoshub.frontend.securityContext=null \
|
||||
--set-json 'kerberoshub.frontend.volumes=[]' \
|
||||
--set-json 'kerberoshub.frontend.volumeMounts=[]')"
|
||||
for name in hub-frontend hub-frontend-demo; do
|
||||
deployment="$(resource Deployment "$name" <<< "$legacy")"
|
||||
assert_contains "$deployment" 'containerPort: 80$'
|
||||
assert_contains "$deployment" 'image: "ghcr.io/uug-ai/hub-frontend:v1.13.9"$'
|
||||
if grep -Eq 'securityContext:|mountPath: /tmp' <<< "$deployment"; then
|
||||
echo "Legacy frontend retains incompatible hardened runtime settings" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ "${CLUSTER_SMOKE:-false}" == true ]]; then
|
||||
namespace=frontend-runtime-test
|
||||
kubectl create namespace "$namespace"
|
||||
helm template runtime "$CHART_DIR" "${values[@]}" --namespace "$namespace" \
|
||||
--set mode=ui --set ingress="" --set kerberoshub.frontend.demoEnabled=true \
|
||||
--show-only templates/kerberos-hub/hub-frontend.yaml \
|
||||
--show-only templates/kerberos-hub/hub-frontend-demo.yaml | kubectl apply -f -
|
||||
pid=""
|
||||
cleanup() {
|
||||
if [[ -n "$pid" ]]; then kill "$pid"; fi
|
||||
if [[ "$1" != 0 ]]; then
|
||||
kubectl -n "$namespace" get pods
|
||||
kubectl -n "$namespace" describe pods
|
||||
kubectl -n "$namespace" logs -l app=hub-frontend --all-containers=true
|
||||
kubectl -n "$namespace" logs -l app=hub-frontend-demo --all-containers=true
|
||||
fi
|
||||
}
|
||||
trap 'cleanup "$?"' EXIT
|
||||
for name in hub-frontend hub-frontend-demo; do
|
||||
kubectl -n "$namespace" rollout status "deployment/$name" --timeout=180s
|
||||
kubectl -n "$namespace" port-forward "service/$name-svc" 18080:80 &
|
||||
pid=$!
|
||||
for attempt in {1..30}; do
|
||||
if curl --fail --silent http://127.0.0.1:18080/healthz > /dev/null; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
[[ "$(curl --fail --silent http://127.0.0.1:18080/healthz)" == ok ]]
|
||||
curl --fail --silent http://127.0.0.1:18080/assets/env.js | grep 'window' > /dev/null
|
||||
kill "$pid"
|
||||
wait "$pid" || [[ "$?" == 143 ]]
|
||||
pid=""
|
||||
echo "OK: $name serves health and generated runtime configuration through Service port 80"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Frontend runtime checks passed."
|
||||
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
components=(
|
||||
kerberospipeline.counting kerberospipeline.throttler
|
||||
kerberospipeline.notify
|
||||
kerberospipeline.thumbnail kerberospipeline.dominantColor
|
||||
kerberoshub.cleanup kerberoshub.monitordevice
|
||||
kerberoshub.services.workflows kerberoshub.services.loitering
|
||||
)
|
||||
fixtures=(
|
||||
--set kerberospipeline.dominantColor.enabled=true
|
||||
--set kerberoshub.workflows.enabled=true
|
||||
--set kerberoshub.services.loitering.enabled=true
|
||||
--set kerberoshub.services.loitering.repository=example/loitering
|
||||
--set kerberoshub.services.loitering.tag=test
|
||||
--set kerberoshub.services.loitering.queue=loitering
|
||||
--set mongodb.tls.enabled=true
|
||||
--set mongodb.tls.existingSecret=mongodb-ca
|
||||
--set mongodb.tls.caFileName=ca.crt
|
||||
)
|
||||
security=()
|
||||
for component in "${components[@]}"; do
|
||||
security+=(
|
||||
--set "$component.securityContext.runAsNonRoot=true"
|
||||
--set "$component.securityContext.runAsUser=65532"
|
||||
--set "$component.securityContext.runAsGroup=65532"
|
||||
--set "$component.securityContext.readOnlyRootFilesystem=true"
|
||||
--set "$component.securityContext.allowPrivilegeEscalation=false"
|
||||
--set "$component.securityContext.capabilities.drop[0]=ALL"
|
||||
--set "$component.securityContext.seccompProfile.type=RuntimeDefault"
|
||||
--set "$component.podSecurityContext.fsGroup=65532"
|
||||
--set "$component.volumes[0].name=scratch"
|
||||
--set "$component.volumes[0].emptyDir.sizeLimit=4Gi"
|
||||
--set "$component.volumeMounts[0].name=scratch"
|
||||
--set "$component.volumeMounts[0].mountPath=/tmp"
|
||||
--set "$component.resources.requests.ephemeral-storage=4Gi"
|
||||
--set "$component.resources.limits.ephemeral-storage=6Gi"
|
||||
)
|
||||
done
|
||||
|
||||
resource() {
|
||||
local kind="$1" name="$2"
|
||||
awk -v kind="$kind" -v name="$name" '
|
||||
function emit() { if (matchedKind && matchedName) printf "%s", block }
|
||||
/^---$/ { emit(); block=""; matchedKind=0; matchedName=0 }
|
||||
{ block=block $0 "\n" }
|
||||
$0 == "kind: " kind { matchedKind=1 }
|
||||
$0 == " name: " name { matchedName=1 }
|
||||
END { emit() }
|
||||
'
|
||||
}
|
||||
|
||||
assert_line() {
|
||||
local block="$1" pattern="$2"
|
||||
if ! grep -Eq "$pattern" <<< "$block"; then
|
||||
printf 'Missing expected pattern: %s\n%s\n' "$pattern" "$block" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
without_admin() {
|
||||
awk '
|
||||
/^---$/ { skip=0 }
|
||||
/^# Source: hub\/templates\/admin\/deployment\.yaml$/ { skip=1 }
|
||||
!skip { print }
|
||||
'
|
||||
}
|
||||
|
||||
without_frontends() {
|
||||
awk '
|
||||
/^---$/ { skip=0 }
|
||||
/^# Source: hub\/templates\/kerberos-hub\/(hub-frontend(-demo)?|hub-api)\.yaml$/ { skip=1 }
|
||||
!skip { print }
|
||||
'
|
||||
}
|
||||
|
||||
for mode in all pipeline ui; do
|
||||
defaults="$(helm template hub "$CHART_DIR" --set "mode=$mode")"
|
||||
# Frontends, hub-api and Admin (since 0.184.0) are hardened by default.
|
||||
worker_defaults="$(without_frontends <<< "$defaults" | without_admin)"
|
||||
if grep -q 'securityContext:' <<< "$worker_defaults"; then
|
||||
echo "Default $mode mode unexpectedly enables worker security settings" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
legacy="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}")"
|
||||
hardened="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}" "${security[@]}")"
|
||||
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${fixtures[@]}" "${security[@]}"
|
||||
names=()
|
||||
if [[ "$mode" != ui ]]; then
|
||||
names+=(pipe-counting pipe-throttler pipe-notify pipe-thumbnail pipe-dominantcolor hub-workflows hub-loitering)
|
||||
fi
|
||||
if [[ "$mode" != pipeline ]]; then
|
||||
names+=(hub-cleanup hub-monitor-device)
|
||||
fi
|
||||
for name in "${names[@]}"; do
|
||||
block="$(resource Deployment "$name" <<< "$hardened")"
|
||||
for pattern in \
|
||||
'^[ ]{6}securityContext:$' '^[ ]{8}fsGroup: 65532$' \
|
||||
'^[ ]+(runAsUser|runAsGroup): 65532$' \
|
||||
'^[ ]+runAsNonRoot: true$' '^[ ]+readOnlyRootFilesystem: true$' \
|
||||
'^[ ]+allowPrivilegeEscalation: false$' '^[ ]+capabilities:$' \
|
||||
'^[ ]+drop:$' '^[ ]+- ALL$' '^[ ]+seccompProfile:$' \
|
||||
'^[ ]+type: RuntimeDefault$' '^[ ]+(- )?mountPath: /tmp$' \
|
||||
'^[ ]+sizeLimit: 4Gi$' '^[ ]+ephemeral-storage: 6Gi$' \
|
||||
'^[ ]+ephemeral-storage: 4Gi$'; do
|
||||
assert_line "$block" "$pattern"
|
||||
done
|
||||
# Verify both identity axes independently.
|
||||
assert_line "$block" '^[ ]+runAsUser: 65532$'
|
||||
assert_line "$block" '^[ ]+runAsGroup: 65532$'
|
||||
assert_line "$block" '^[ ]{8,10}securityContext:$'
|
||||
if [[ "$name" == hub-cleanup || "$name" == hub-monitor-device || "$name" == hub-workflows || "$name" == pipe-notify ]]; then
|
||||
assert_line "$block" '^[ ]+secretName: mongodb-ca$'
|
||||
assert_line "$block" '^[ ]+mountPath: /etc/mongodb/tls$'
|
||||
assert_line "$block" '^[ ]+readOnly: true$'
|
||||
fi
|
||||
if [[ "$name" == pipe-notify ]]; then
|
||||
# Provider, queue, FFmpeg and all other worker settings are unchanged.
|
||||
old_block="$(resource Deployment pipe-notify <<< "$legacy")"
|
||||
[[ "$(sed -n '/^ env:/,$p' <<< "$old_block")" == "$(sed -n '/^ env:/,$p' <<< "$block")" ]]
|
||||
fi
|
||||
if [[ "$name" != hub-monitor-device ]]; then
|
||||
service="$(resource Service "$name" <<< "$hardened")"
|
||||
assert_line "$service" '^[ ]+port: 8080$'
|
||||
assert_line "$service" '^[ ]+targetPort: 8080$'
|
||||
fi
|
||||
done
|
||||
expected="${#names[@]}"
|
||||
[[ "$(without_frontends <<< "$hardened" | without_admin | grep -c 'runAsUser: 65532')" == "$expected" ]]
|
||||
[[ "$(without_frontends <<< "$hardened" | without_admin | grep -c 'fsGroup: 65532')" == "$expected" ]]
|
||||
|
||||
# Image selection, Services, env and TLS mounts must not change.
|
||||
for pattern in '^[ ]+image:' '^[ ]+(port|targetPort|containerPort):' 'mongodb-tls'; do
|
||||
[[ "$(grep -E "$pattern" <<< "$legacy")" == "$(grep -E "$pattern" <<< "$hardened")" ]]
|
||||
done
|
||||
echo "OK ($mode): defaults unchanged; $expected independent hardened workers preserve images, ports and MongoDB TLS"
|
||||
done
|
||||
|
||||
# Hardening one worker must not opt in another, even on the same pod mode.
|
||||
isolated="$(helm template hub "$CHART_DIR" --set mode=pipeline \
|
||||
--set kerberospipeline.counting.securityContext.runAsUser=65532)"
|
||||
[[ "$(grep -c 'runAsUser: 65532' <<< "$isolated")" == 1 ]]
|
||||
assert_line "$(resource Deployment pipe-counting <<< "$isolated")" '^[ ]+runAsUser: 65532$'
|
||||
echo "All hardened worker checks passed."
|
||||
|
||||
# Since chart 0.184.0 the hardened Admin runtime is the default; these flags
|
||||
# opt back into a legacy image on port 80.
|
||||
legacy_admin_flags=(
|
||||
--set admin.repository=uugai/admin
|
||||
--set admin.tag=v1.3.0
|
||||
--set admin.containerPort=80
|
||||
--set admin.securityContext=null
|
||||
--set admin.readinessProbe=null
|
||||
--set admin.livenessProbe=null
|
||||
--set admin.volumes=null
|
||||
--set admin.volumeMounts=null
|
||||
--set admin.oauth2Proxy.enabled=true
|
||||
)
|
||||
for mode in all ui pipeline; do
|
||||
legacy="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${legacy_admin_flags[@]}")"
|
||||
configured="$(helm template hub "$CHART_DIR" --set "mode=$mode" --set admin.oauth2Proxy.enabled=true)"
|
||||
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${legacy_admin_flags[@]}"
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
[[ -z "$(resource Deployment admin <<< "$configured")" ]]
|
||||
[[ -z "$(resource Service admin-svc <<< "$configured")" ]]
|
||||
[[ "$legacy" == "$configured" ]]
|
||||
echo "OK (pipeline): Admin settings render no Admin resources or unrelated changes"
|
||||
continue
|
||||
fi
|
||||
old="$(resource Deployment admin <<< "$legacy")"
|
||||
block="$(resource Deployment admin <<< "$configured")"
|
||||
assert_line "$old" '^[ ]+containerPort: 80$'
|
||||
[[ "$old" != *securityContext:* && "$old" != *admin-tmp* ]]
|
||||
for pattern in \
|
||||
'^[ ]+containerPort: 8080$' '^[ ]{10}securityContext:$' \
|
||||
'^[ ]+runAsUser: 65532$' '^[ ]+runAsGroup: 65532$' \
|
||||
'^[ ]+runAsNonRoot: true$' '^[ ]+readOnlyRootFilesystem: true$' \
|
||||
'^[ ]+allowPrivilegeEscalation: false$' '^[ ]+capabilities:$' \
|
||||
'^[ ]+drop:$' '^[ ]+- ALL$' '^[ ]+seccompProfile:$' \
|
||||
'^[ ]+type: RuntimeDefault$' '^[ ]+medium: Memory$' \
|
||||
'^[ ]+sizeLimit: 16Mi$' '^[ ]+(- )?mountPath: /tmp$'; do
|
||||
assert_line "$block" "$pattern"
|
||||
done
|
||||
old_service="$(resource Service admin-svc <<< "$legacy")"
|
||||
service="$(resource Service admin-svc <<< "$configured")"
|
||||
assert_line "$old_service" '^[ ]+targetPort: http$'
|
||||
assert_line "$service" '^[ ]+port: 80$'
|
||||
assert_line "$service" '^[ ]+targetPort: http$'
|
||||
[[ "$(resource Ingress admin-ingress <<< "$legacy")" == "$(resource Ingress admin-ingress <<< "$configured")" ]]
|
||||
[[ "$(resource Deployment oauth2-proxy-admin <<< "$legacy")" == "$(resource Deployment oauth2-proxy-admin <<< "$configured")" ]]
|
||||
[[ "$(resource Service oauth2-proxy-admin <<< "$legacy")" == "$(resource Service oauth2-proxy-admin <<< "$configured")" ]]
|
||||
[[ "$(without_admin <<< "$legacy" | grep 'image:')" == "$(without_admin <<< "$configured" | grep 'image:')" ]]
|
||||
assert_line "$old" 'image: "uugai/admin:v1.3.0"$'
|
||||
assert_line "$block" 'image: "ghcr.io/uug-ai/admin:v1.4.6"$'
|
||||
# No other workload inherits Admin's container port or security settings.
|
||||
[[ "$(without_frontends <<< "$configured" | grep -c 'runAsUser: 65532')" == 1 ]]
|
||||
echo "OK ($mode): Admin hardened defaults; legacy opt-out; Service port, ingress and OAuth2-proxy preserved"
|
||||
done
|
||||
echo "All hardened Admin checks passed."
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
REAL_KUBECTL="$(command -v kubectl)"
|
||||
export REAL_KUBECTL
|
||||
|
||||
# Substitute only transport: exercise the migration against Kubernetes' real patch engine.
|
||||
kubectl() {
|
||||
if [[ "$*" == *" get deployment "* ]]; then
|
||||
printf '%s\n' "$LIVE"
|
||||
else
|
||||
local patch="" previous="" argument
|
||||
for argument in "$@"; do
|
||||
if [[ "$previous" == -p ]]; then patch="$argument"; fi
|
||||
previous="$argument"
|
||||
done
|
||||
if [[ "${EXPECT_APPLY:-false}" == true ]]; then
|
||||
[[ "$*" != *"--dry-run=server"* ]] || return 1
|
||||
else
|
||||
[[ "$*" == *"--dry-run=server"* ]] || return 1
|
||||
fi
|
||||
local current="$LIVE"
|
||||
if [[ "${SIMULATE_RACE:-false}" == true ]]; then
|
||||
current="$(jq '.metadata.resourceVersion = "2"' <<< "$LIVE")"
|
||||
fi
|
||||
"$REAL_KUBECTL" patch --local -f <(printf '%s\n' "$current") \
|
||||
--type=json -p "$patch" -o json
|
||||
fi
|
||||
}
|
||||
export -f kubectl
|
||||
|
||||
for deployment in admin hub-frontend hub-frontend-demo; do
|
||||
for old in 80 8080; do
|
||||
target=8080
|
||||
if [[ "$old" == 8080 ]]; then target=80; fi
|
||||
LIVE="$(jq -nc --arg name "$deployment" --argjson port "$old" '{
|
||||
apiVersion: "apps/v1", kind: "Deployment",
|
||||
metadata: {name: $name, resourceVersion: "1"},
|
||||
spec: {selector: {matchLabels: {app: $name}}, template: {
|
||||
metadata: {labels: {app: $name}}, spec: {containers: [
|
||||
{name: "sidecar", image: "example/sidecar:unchanged"},
|
||||
{name: $name, image: "example/frontend:unchanged", ports: [
|
||||
{name: "http", containerPort: $port},
|
||||
{name: "metrics", containerPort: 2112}
|
||||
]}
|
||||
]}
|
||||
}}
|
||||
}')"
|
||||
export LIVE
|
||||
merge="$(jq -nc --arg name "$deployment" --argjson port "$target" \
|
||||
'{spec:{template:{spec:{containers:[{name:$name,ports:[{name:"http",containerPort:$port}]}]}}}}')"
|
||||
merged="$("$REAL_KUBECTL" patch --local -f <(printf '%s\n' "$LIVE") \
|
||||
--type=strategic -p "$merge" -o json)"
|
||||
jq -e '[.spec.template.spec.containers[] | .ports[]? |
|
||||
select(.name == "http")] | length == 2' <<< "$merged" > /dev/null
|
||||
|
||||
fixed="$(bash "$ROOT/scripts/migrate-http-port.sh" test "$deployment" "$target")"
|
||||
jq -e --argjson port "$target" '
|
||||
[.spec.template.spec.containers[] | .ports[]? | select(.name == "http")] |
|
||||
length == 1 and .[0].containerPort == $port
|
||||
' <<< "$fixed" > /dev/null
|
||||
[[ "$(jq -Sc '.spec.template.spec.containers[0]' <<< "$fixed")" == \
|
||||
"$(jq -Sc '.spec.template.spec.containers[0]' <<< "$LIVE")" ]]
|
||||
[[ "$(jq -Sc '.spec.template.spec.containers[1] | del(.ports)' <<< "$fixed")" == \
|
||||
"$(jq -Sc '.spec.template.spec.containers[1] | del(.ports)' <<< "$LIVE")" ]]
|
||||
jq -e '.spec.template.spec.containers[1].ports |
|
||||
any(.name == "metrics" and .containerPort == 2112)' <<< "$fixed" > /dev/null
|
||||
|
||||
LIVE="$fixed"
|
||||
again="$(EXPECT_APPLY=true bash "$ROOT/scripts/migrate-http-port.sh" test "$deployment" "$target" --apply)"
|
||||
[[ "$(jq -Sc . <<< "$again")" == "$(jq -Sc . <<< "$fixed")" ]]
|
||||
LIVE="$merged"
|
||||
repaired="$(EXPECT_APPLY=true bash "$ROOT/scripts/migrate-http-port.sh" test "$deployment" "$target" --apply)"
|
||||
jq -e '[.spec.template.spec.containers[] | .ports[]? |
|
||||
select(.name == "http")] | length == 1' <<< "$repaired" > /dev/null
|
||||
|
||||
if [[ "${SERVER_VALIDATION:-false}" == true ]]; then
|
||||
if "$REAL_KUBECTL" create --dry-run=server \
|
||||
-f <(jq 'del(.metadata.resourceVersion)' <<< "$merged") > /dev/null 2>&1; then
|
||||
echo "Expected API rejection of duplicate http ports" >&2
|
||||
exit 1
|
||||
fi
|
||||
"$REAL_KUBECTL" create --dry-run=server \
|
||||
-f <(jq 'del(.metadata.resourceVersion)' <<< "$repaired") > /dev/null
|
||||
fi
|
||||
echo "OK: $deployment $old -> $target; duplicate reproduced, replacement and rollback safe"
|
||||
done
|
||||
done
|
||||
|
||||
if SIMULATE_RACE=true bash "$ROOT/scripts/migrate-http-port.sh" test hub-frontend-demo 8080 > /dev/null 2>&1; then
|
||||
echo "Expected rejection of concurrent Deployment changes" >&2
|
||||
exit 1
|
||||
fi
|
||||
LIVE="$(jq '.spec.template.spec.containers[1].ports = [{name:"http",containerPort:9000}]' <<< "$LIVE")"
|
||||
if bash "$ROOT/scripts/migrate-http-port.sh" test hub-frontend-demo 8080 > /dev/null 2>&1; then
|
||||
echo "Expected rejection of an unknown HTTP port" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "HTTP port migration checks passed."
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
resource() {
|
||||
local kind="$1" name="$2"
|
||||
awk -v kind="$kind" -v name="$name" '
|
||||
function emit() { if (matchedKind && matchedName) printf "%s", block }
|
||||
/^---$/ { emit(); block=""; matchedKind=0; matchedName=0 }
|
||||
{ block=block $0 "\n" }
|
||||
$0 == "kind: " kind { matchedKind=1 }
|
||||
$0 == " name: " name { matchedName=1 }
|
||||
END { emit() }
|
||||
'
|
||||
}
|
||||
|
||||
assert_line() {
|
||||
if ! grep -Eq -- "$2" <<< "$1"; then
|
||||
printf 'Missing expected Hub API setting: %s\n' "$2" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
fixtures=(
|
||||
--set workflowConfiguration.enabled=true
|
||||
--set mongodb.tls.enabled=true
|
||||
--set mongodb.tls.existingSecret=mongodb-ca
|
||||
--set kerberoshub.api.serverTLS.enabled=true
|
||||
--set kerberoshub.api.serverTLS.secretName=api-tls
|
||||
)
|
||||
|
||||
for mode in all ui pipeline; do
|
||||
defaults="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}")"
|
||||
legacy="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}" \
|
||||
--set kerberoshub.api.securityContext=null \
|
||||
--set kerberoshub.api.podSecurityContext=null)"
|
||||
configured="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}" \
|
||||
--set kerberoshub.api.securityContext.runAsUser=1000 \
|
||||
--set kerberoshub.api.securityContext.runAsGroup=1000 \
|
||||
--set kerberoshub.api.podSecurityContext.fsGroup=1000)"
|
||||
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${fixtures[@]}"
|
||||
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
[[ -z "$(resource Deployment hub-api <<< "$defaults")" ]]
|
||||
[[ "$defaults" == "$legacy" && "$defaults" == "$configured" ]]
|
||||
echo "OK (pipeline): no Hub API resources or unrelated changes"
|
||||
continue
|
||||
fi
|
||||
|
||||
api="$(resource Deployment hub-api <<< "$defaults")"
|
||||
for pattern in \
|
||||
'^[ ]{6}securityContext:$' '^[ ]{8}fsGroup: 65532$' \
|
||||
'^[ ]{10}securityContext:$' '^[ ]{12}runAsUser: 65532$' \
|
||||
'^[ ]{12}runAsGroup: 65532$' '^[ ]{12}runAsNonRoot: true$' \
|
||||
'^[ ]{12}readOnlyRootFilesystem: true$' \
|
||||
'^[ ]{12}allowPrivilegeEscalation: false$' '^[ ]{12}capabilities:$' \
|
||||
'^[ ]{14}drop:$' '^[ ]{14}- ALL$' \
|
||||
'^[ ]{12}seccompProfile:$' '^[ ]{14}type: RuntimeDefault$' \
|
||||
'^[ ]+(- )?name: hub-api-tmp$' '^[ ]+(- )?emptyDir: \{\}$' \
|
||||
'^[ ]+(- )?mountPath: /tmp$' '^[ ]+secretName: mongodb-ca$' \
|
||||
'^[ ]+secretName: api-tls$' '^[ ]+mountPath: /etc/mongodb/tls$' \
|
||||
'^[ ]+mountPath: /etc/hub-api/tls$' \
|
||||
'^[ ]+mountPath: /etc/kerberos/configuration$' \
|
||||
'^[ ]+mountPath: /etc/kerberos/classifications$'; do
|
||||
assert_line "$api" "$pattern"
|
||||
done
|
||||
[[ "$(grep -c 'securityContext:' <<< "$api")" == 2 ]]
|
||||
old_api="$(resource Deployment hub-api <<< "$legacy")"
|
||||
if grep -q 'securityContext:' <<< "$old_api"; then
|
||||
echo "Legacy Hub API opt-out still renders a security context" >&2
|
||||
exit 1
|
||||
fi
|
||||
custom_api="$(resource Deployment hub-api <<< "$configured")"
|
||||
for field in runAsUser runAsGroup fsGroup; do
|
||||
assert_line "$custom_api" "^[ ]+$field: 1000$"
|
||||
done
|
||||
|
||||
# Only security settings change; preserve env, mounts, images and routing.
|
||||
for pattern in '^[ ]+image:' '^[ ]+(port|targetPort|containerPort):' \
|
||||
'^[ ]+(- )?(name|mountPath|secretName|value):'; do
|
||||
[[ "$(grep -E "$pattern" <<< "$defaults")" == "$(grep -E "$pattern" <<< "$legacy")" ]]
|
||||
[[ "$(grep -E "$pattern" <<< "$defaults")" == "$(grep -E "$pattern" <<< "$configured")" ]]
|
||||
done
|
||||
echo "OK ($mode): API security defaults, overrides, opt-out, scratch and TLS/config mounts"
|
||||
done
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
extract_mcp() {
|
||||
awk '
|
||||
/^---/ { deployment=0; name=""; variable="" }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
deployment && /^ name:/ { name=$2 }
|
||||
/- name: MCP_/ { variable=$3; next }
|
||||
variable != "" && /value:/ {
|
||||
value=$0
|
||||
sub(/^[[:space:]]*value: /, "", value)
|
||||
print (deployment ? name : "non-deployment"), variable, value
|
||||
variable=""
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
assert_mcp() {
|
||||
local rendered="$1" expected="$2" actual
|
||||
actual="$(printf '%s\n' "$rendered" | extract_mcp)"
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
printf 'Unexpected MCP environment:\n%s\nExpected:\n%s\n' "$actual" "$expected" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
defaults="$(printf '%s\n' 'hub-api MCP_ALLOWED_ORIGINS ""' 'hub-api MCP_ENABLED "false"')"
|
||||
enabled="$(printf '%s\n' \
|
||||
'hub-api MCP_ALLOWED_ORIGINS "https://agent.example.com,http://localhost:4200"' \
|
||||
'hub-api MCP_ENABLED "true"')"
|
||||
flags=(
|
||||
--set kerberoshub.api.mcp.enabled=true
|
||||
--set-json 'kerberoshub.api.mcp.allowedOrigins=["https://agent.example.com","http://localhost:4200"]'
|
||||
)
|
||||
|
||||
for mode in all ui pipeline; do
|
||||
default_render="$(helm template hub "$CHART_DIR" --set "mode=$mode")"
|
||||
configured_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${flags[@]}")"
|
||||
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${flags[@]}"
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
assert_mcp "$default_render" ""
|
||||
assert_mcp "$configured_render" ""
|
||||
[[ "$default_render" == "$configured_render" ]]
|
||||
else
|
||||
assert_mcp "$default_render" "$defaults"
|
||||
assert_mcp "$configured_render" "$enabled"
|
||||
rest_default="$(grep -A1 -- '- name: CORS_ALLOWED_ORIGINS' <<< "$default_render")"
|
||||
rest_configured="$(grep -A1 -- '- name: CORS_ALLOWED_ORIGINS' <<< "$configured_render")"
|
||||
[[ "$rest_default" == "$rest_configured" ]]
|
||||
fi
|
||||
echo "OK ($mode): MCP defaults, overrides, API-only environment and REST CORS isolation"
|
||||
done
|
||||
|
||||
assert_mcp "$(helm template hub "$CHART_DIR" --set kerberoshub.api.mcp.enabled=true)" \
|
||||
"$(printf '%s\n' 'hub-api MCP_ALLOWED_ORIGINS ""' 'hub-api MCP_ENABLED "true"')"
|
||||
assert_mcp "$(helm template hub "$CHART_DIR" --set kerberoshub.api.mcp=null)" "$defaults"
|
||||
assert_mcp "$(helm template hub "$CHART_DIR" "${flags[@]}" --set kerberoshub.api.mcp.enabled=false)" \
|
||||
"$(printf '%s\n' 'hub-api MCP_ALLOWED_ORIGINS "https://agent.example.com,http://localhost:4200"' 'hub-api MCP_ENABLED "false"')"
|
||||
|
||||
expect_invalid() {
|
||||
local output
|
||||
if output="$(helm template hub "$CHART_DIR" "$@" 2>&1)"; then
|
||||
echo "Invalid MCP settings unexpectedly rendered: $*" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$output" != *"mcp"* ]]; then
|
||||
printf 'Rendering failed for an unexpected reason:\n%s\n' "$output" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
expect_invalid --set-string kerberoshub.api.mcp.enabled=true
|
||||
expect_invalid --set-string kerberoshub.api.mcp.allowedOrigins=https://agent.example.com
|
||||
expect_invalid --set-string kerberoshub.api.mcp.origin=https://agent.example.com
|
||||
for origin in 'https://*.example.com' 'https://agent.example.com/' \
|
||||
'https://agent.example.com/path' 'https://agent.example.com?query' \
|
||||
'https://agent.example.com#fragment' 'https://user@agent.example.com' \
|
||||
'https://agent.example.com,https://other.example.com' 'https://bad host' 'ftp://agent.example.com'; do
|
||||
expect_invalid --set-json "kerberoshub.api.mcp.allowedOrigins=[\"$origin\"]"
|
||||
done
|
||||
expect_invalid --set-json 'kerberoshub.api.mcp.allowedOrigins=["https://agent.example.com","https://agent.example.com"]'
|
||||
|
||||
echo "All Hub MCP configuration checks passed."
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
extract_passkeys() {
|
||||
awk '
|
||||
/^---/ { deployment=0; name=""; variable="" }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
deployment && /^ name:/ { name=$2 }
|
||||
deployment && /- name: PASSKEY_/ { variable=$3; next }
|
||||
variable != "" && /value:/ {
|
||||
value=$0
|
||||
sub(/^[[:space:]]*value: /, "", value)
|
||||
print name, variable, value
|
||||
variable=""
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
assert_passkeys() {
|
||||
local rendered="$1" expected="$2" actual count expected_count
|
||||
actual="$(printf '%s\n' "$rendered" | extract_passkeys)"
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
printf 'Unexpected passkey environment:\n%s\nExpected:\n%s\n' "$actual" "$expected" >&2
|
||||
return 1
|
||||
fi
|
||||
count="$(printf '%s\n' "$rendered" | awk '/- name: PASSKEY_/ { count++ } END { print count+0 }')"
|
||||
expected_count="$(printf '%s\n' "$expected" | awk 'NF { count++ } END { print count+0 }')"
|
||||
if [[ "$count" != "$expected_count" ]]; then
|
||||
echo "Passkey variables leaked outside the expected Deployment or were duplicated" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
extract_feature() {
|
||||
awk '
|
||||
/^---/ { deployment=0; name=""; flag=0 }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
deployment && /^ name:/ { name=$2 }
|
||||
deployment && /- name: FEATURE_PASSKEYS_ENABLED$/ { flag=1; next }
|
||||
flag && /value:/ {
|
||||
value=$0
|
||||
sub(/^[[:space:]]*value: /, "", value)
|
||||
print name, value
|
||||
flag=0
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
assert_feature() {
|
||||
local rendered="$1" expected="$2" actual
|
||||
actual="$(printf '%s\n' "$rendered" | extract_feature)"
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
printf 'Unexpected FEATURE_PASSKEYS_ENABLED:\n%s\nExpected:\n%s\n' "$actual" "$expected" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
CONFIGURED_FLAGS=(
|
||||
--set-json kerberoshub.api.passkeys.enabled=true
|
||||
--set-json 'kerberoshub.api.passkeys.rpId="example.com"'
|
||||
--set-json 'kerberoshub.api.passkeys.origins=["https://hub.example.com","https://legacy.example.com:8443"]'
|
||||
--set-json 'kerberoshub.api.passkeys.rpName="Example Hub"'
|
||||
)
|
||||
expected="$(printf '%s\n' \
|
||||
'hub-api PASSKEY_ORIGINS "https://hub.example.com,https://legacy.example.com:8443"' \
|
||||
'hub-api PASSKEY_RP_ID "example.com"' \
|
||||
'hub-api PASSKEY_RP_NAME "Example Hub"' | sort)"
|
||||
|
||||
for mode in all ui pipeline; do
|
||||
default_render="$(helm template hub "$CHART_DIR" --set "mode=$mode")"
|
||||
assert_passkeys "$default_render" ""
|
||||
configured_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${CONFIGURED_FLAGS[@]}")"
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
assert_passkeys "$configured_render" ""
|
||||
assert_feature "$default_render" ""
|
||||
assert_feature "$configured_render" ""
|
||||
else
|
||||
assert_passkeys "$configured_render" "$expected"
|
||||
assert_feature "$default_render" 'hub-frontend "false"'
|
||||
assert_feature "$configured_render" "$(printf '%s\n' 'hub-api "true"' 'hub-frontend "true"')"
|
||||
fi
|
||||
echo "OK ($mode): defaults opt out; enabled settings configure Hub API and flag the frontend"
|
||||
done
|
||||
|
||||
disabled_render="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" --set kerberoshub.api.passkeys.enabled=false)"
|
||||
assert_passkeys "$disabled_render" ""
|
||||
assert_feature "$disabled_render" 'hub-frontend "false"'
|
||||
|
||||
demo_render="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" --set kerberoshub.frontend.demoEnabled=true)"
|
||||
assert_feature "$demo_render" "$(printf '%s\n' 'hub-api "true"' 'hub-frontend "true"' 'hub-frontend-demo "true"')"
|
||||
|
||||
localhost_render="$(helm template hub "$CHART_DIR" --set mode=ui \
|
||||
--set kerberoshub.api.passkeys.enabled=true \
|
||||
--set-string kerberoshub.api.passkeys.rpId=localhost \
|
||||
--set-json 'kerberoshub.api.passkeys.origins=["http://localhost:4200"]')"
|
||||
assert_passkeys "$localhost_render" "$(printf '%s\n' \
|
||||
'hub-api PASSKEY_ORIGINS "http://localhost:4200"' \
|
||||
'hub-api PASSKEY_RP_ID "localhost"' \
|
||||
'hub-api PASSKEY_RP_NAME "Kerberos Hub"' | sort)"
|
||||
|
||||
legacy_render="$(helm template hub "$CHART_DIR" --set mode=ui \
|
||||
--set-json 'kerberoshub.extraEnv=[{"name":"PASSKEY_RP_ID","value":"example.com"}]')"
|
||||
printf '%s\n' "$legacy_render" | grep -q -- '- name: PASSKEY_RP_ID'
|
||||
|
||||
expect_invalid() {
|
||||
local output
|
||||
if output="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" "$@" 2>&1)"; then
|
||||
echo "Invalid passkey settings unexpectedly rendered: $*" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$output" != *"passkeys"* ]]; then
|
||||
printf 'Rendering failed for an unexpected reason:\n%s\n' "$output" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
expect_invalid --set-string kerberoshub.api.passkeys.rpId=
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=[]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=["https://hub.example.com/"]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=["http://hub.example.com"]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=["https://hub.example.com","https://hub.example.com"]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins="https://hub.example.com"'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.enabled="true"'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.rpId=123'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.rpName=123'
|
||||
expect_invalid --set-string kerberoshub.api.passkeys.origin=https://hub.example.com
|
||||
|
||||
echo "All Hub passkey configuration checks passed."
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 3 || $# -gt 4 ]]; then
|
||||
echo "Usage: bash scripts/migrate-http-port.sh NAMESPACE DEPLOYMENT PORT [--apply]" >&2
|
||||
exit 1
|
||||
fi
|
||||
namespace="$1" deployment="$2" port="$3"
|
||||
case "$deployment" in
|
||||
admin|hub-frontend|hub-frontend-demo) ;;
|
||||
*) echo "Unsupported Deployment: $deployment" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$port" in
|
||||
80|8080) ;;
|
||||
*) echo "Expected HTTP port 80 or 8080, got: $port" >&2; exit 1 ;;
|
||||
esac
|
||||
dry_run=(--dry-run=server)
|
||||
if [[ $# -eq 4 ]]; then
|
||||
if [[ "$4" != --apply ]]; then
|
||||
echo "Unknown option: $4" >&2
|
||||
exit 1
|
||||
fi
|
||||
dry_run=()
|
||||
fi
|
||||
|
||||
live="$(kubectl -n "$namespace" get deployment "$deployment" -o json)"
|
||||
patch="$(jq -ce --arg container "$deployment" --argjson port "$port" '
|
||||
. as $deployment |
|
||||
[.spec.template.spec.containers | to_entries[] |
|
||||
select(.value.name == $container)] |
|
||||
if length != 1 then error("Expected exactly one matching container") else .[0] end |
|
||||
.key as $index | .value.ports as $ports |
|
||||
if ($ports | type) != "array" then error("Container ports must be an array") else . end |
|
||||
[$ports[] | select(.name == "http")] as $http |
|
||||
if ($http | length) == 0 then error("No named http port to migrate") else . end |
|
||||
if any($http[]; (.containerPort != 80 and .containerPort != 8080) or
|
||||
((.protocol // "TCP") != "TCP") or has("hostPort") or has("hostIP"))
|
||||
then error("Unsupported http port configuration; migrate manually") else . end |
|
||||
if any($ports[]; .name != "http" and .containerPort == $port and
|
||||
((.protocol // "TCP") == "TCP"))
|
||||
then error("Target port is already used by another named port") else . end |
|
||||
([$ports[] | select(.name != "http")] +
|
||||
[($http[0] + {containerPort: $port})]) as $replacement |
|
||||
[
|
||||
{op: "test", path: "/metadata/resourceVersion", value: $deployment.metadata.resourceVersion},
|
||||
{op: "test", path: ("/spec/template/spec/containers/" + ($index | tostring) + "/name"),
|
||||
value: $container},
|
||||
{op: "replace", path: ("/spec/template/spec/containers/" + ($index | tostring) + "/ports"),
|
||||
value: $replacement}
|
||||
]
|
||||
' <<< "$live")"
|
||||
|
||||
kubectl -n "$namespace" patch deployment "$deployment" --type=json \
|
||||
-p "$patch" "${dry_run[@]}" -o yaml
|
||||
Reference in New Issue
Block a user