This commit is contained in:
James Read 2026-03-02 00:49:13 +00:00 committed by GitHub
commit 235493e471
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 242 additions and 64 deletions

View File

@ -10,6 +10,7 @@
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5050/badge)](https://bestpractices.coreinfrastructure.org/projects/5050) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5050/badge)](https://bestpractices.coreinfrastructure.org/projects/5050)
[![Go Report Card](https://goreportcard.com/badge/github.com/Olivetin/OliveTin)](https://goreportcard.com/report/github.com/OliveTin/OliveTin) [![Go Report Card](https://goreportcard.com/badge/github.com/Olivetin/OliveTin)](https://goreportcard.com/report/github.com/OliveTin/OliveTin)
[![AI Autonomy Level](https://img.shields.io/badge/AI%20Autonomy-Level%201%20of%205%20(assistance--only)-blue)](https://blog.jread.com/posts/ai-levels-of-autonomy-in-software-engineering/)
[OliveTin 2k to 3k upgrade guide](https://docs.olivetin.app/upgrade/2k3k.html) [OliveTin 2k to 3k upgrade guide](https://docs.olivetin.app/upgrade/2k3k.html)
</div> </div>

View File

@ -31,6 +31,12 @@ Please use responsible disclosure practices when reporting a vulnerability. **Yo
* **Option B**: Please email `contact@jread.com` for responsible disclosure. * **Option B**: Please email `contact@jread.com` for responsible disclosure.
The following notes might be helpful when reporting a vulnerability:
* OliveTin does not offer a bug bounty program.
* GitHub usernames are how we you will be credited for discoveries reported via GitHub, if using emails we'll ask for your preferred name/handle to credit you with.
* CVEs will be requested via GitHub Security Advisories when appropriate, but we do not guarantee that all vulnerabilities will receive CVEs, as this is determined on a case-by-case basis.
## Disclosure of how vulnerabilities were found ## Disclosure of how vulnerabilities were found
It is incredibly useful to not just patch security vulnerabilities, but also to understand how they were found. If you are able to share this information, it can help us and the community to better understand potential attack vectors and improve the overall security of the project. It is incredibly useful to not just patch security vulnerabilities, but also to understand how they were found. If you are able to share this information, it can help us and the community to better understand potential attack vectors and improve the overall security of the project.

View File

@ -1,5 +1,6 @@
import { Terminal } from '@xterm/xterm' import { Terminal } from '@xterm/xterm'
import { FitAddon } from '@xterm/addon-fit' import { FitAddon } from '@xterm/addon-fit'
import { WebLinksAddon } from '@xterm/addon-web-links'
import { Mutex } from './Mutex.js' import { Mutex } from './Mutex.js'
/** /**
@ -18,13 +19,24 @@ export class OutputTerminal {
constructor (executionTrackingId) { constructor (executionTrackingId) {
this.executionTrackingId = executionTrackingId this.executionTrackingId = executionTrackingId
this.writeMutex = new Mutex() this.writeMutex = new Mutex()
const linkHandler = {
activate (event, text, _range) {
event.preventDefault()
window.open(text, '_blank')
}
}
this.terminal = new Terminal({ this.terminal = new Terminal({
convertEol: true convertEol: true,
linkHandler
}) })
const fitAddon = new FitAddon() const fitAddon = new FitAddon()
this.terminal.loadAddon(fitAddon) this.terminal.loadAddon(fitAddon)
this.terminal.fit = fitAddon this.terminal.fit = fitAddon
this.terminal.loadAddon(new WebLinksAddon((event, uri) => linkHandler.activate(event, uri)))
this.linkHandlerConfigured = true
} }
async write (out, then) { async write (out, then) {

View File

@ -15,6 +15,7 @@
"@hugeicons/vue": "^1.0.4", "@hugeicons/vue": "^1.0.4",
"@vitejs/plugin-vue": "^6.0.4", "@vitejs/plugin-vue": "^6.0.4",
"@xterm/addon-fit": "^0.11.0", "@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0", "@xterm/xterm": "^6.0.0",
"iconify-icon": "^3.0.2", "iconify-icon": "^3.0.2",
"picocrank": "^1.14.0", "picocrank": "^1.14.0",
@ -1570,6 +1571,12 @@
"integrity": "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==", "integrity": "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@xterm/addon-web-links": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.12.0.tgz",
"integrity": "sha512-4Smom3RPyVp7ZMYOYDoC/9eGJJJqYhnPLGGqJ6wOBfB8VxPViJNSKdgRYb8NpaM6YSelEKbA2SStD7lGyqaobw==",
"license": "MIT"
},
"node_modules/@xterm/xterm": { "node_modules/@xterm/xterm": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz",
@ -4479,9 +4486,9 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"

View File

@ -28,13 +28,14 @@
"@hugeicons/vue": "^1.0.4", "@hugeicons/vue": "^1.0.4",
"@vitejs/plugin-vue": "^6.0.4", "@vitejs/plugin-vue": "^6.0.4",
"@xterm/addon-fit": "^0.11.0", "@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0", "@xterm/xterm": "^6.0.0",
"iconify-icon": "^3.0.2", "iconify-icon": "^3.0.2",
"picocrank": "^1.14.0", "picocrank": "^1.14.0",
"standard": "^17.1.2", "standard": "^17.1.2",
"unplugin-vue-components": "^31.0.0", "unplugin-vue-components": "^31.0.0",
"vite": "^7.3.1", "vite": "^7.3.1",
"vue": "^3.5.29", "vue": "^3.5.29",
"vue-i18n": "^11.2.8", "vue-i18n": "^11.2.8",
"vue-router": "^5.0.3" "vue-router": "^5.0.3"
} }

View File

@ -210,6 +210,11 @@ export declare type EffectivePolicy = Message<"olivetin.api.v1.EffectivePolicy">
* @generated from field: bool show_log_list = 2; * @generated from field: bool show_log_list = 2;
*/ */
showLogList: boolean; showLogList: boolean;
/**
* @generated from field: bool show_version_number = 3;
*/
showVersionNumber: boolean;
}; };
/** /**
@ -1853,4 +1858,3 @@ export declare const OliveTinApiService: GenService<{
output: typeof EntitySchema; output: typeof EntitySchema;
}, },
}>; }>;

File diff suppressed because one or more lines are too long

View File

@ -31,7 +31,7 @@
<footer title="footer" v-if="showFooter"> <footer title="footer" v-if="showFooter">
<p> <p>
<img title="application icon" :src="logoUrl" alt="OliveTin logo" style="height: 1em;" class="logo" /> <img title="application icon" :src="logoUrl" alt="OliveTin logo" style="height: 1em;" class="logo" />
OliveTin {{ currentVersion }} OliveTin <span v-if="showVersionNumber">{{ currentVersion }}</span>
</p> </p>
<p> <p>
<span> <span>
@ -52,7 +52,7 @@
<span>{{ t('connected') }}</span> <span>{{ t('connected') }}</span>
</p> </p>
<p> <p v-if="showVersionNumber">
<a id="available-version" href="http://olivetin.app" target="_blank" hidden>?</a> <a id="available-version" href="http://olivetin.app" target="_blank" hidden>?</a>
</p> </p>
</footer> </footer>
@ -126,6 +126,7 @@ const showFooter = ref(true)
const showNavigation = ref(true) const showNavigation = ref(true)
const showLogs = ref(true) const showLogs = ref(true)
const showDiagnostics = ref(true) const showDiagnostics = ref(true)
const showVersionNumber = ref(true)
const showLoginLink = ref(true) const showLoginLink = ref(true)
const sectionNavigationStyle = ref('sidebar') const sectionNavigationStyle = ref('sidebar')
@ -223,6 +224,7 @@ function updateHeaderFromInit() {
showNavigation.value = window.initResponse.showNavigation showNavigation.value = window.initResponse.showNavigation
showLogs.value = window.initResponse.showLogList showLogs.value = window.initResponse.showLogList
showDiagnostics.value = window.initResponse.showDiagnostics showDiagnostics.value = window.initResponse.showDiagnostics
showVersionNumber.value = window.initResponse.effectivePolicy?.showVersionNumber ?? true
sectionNavigationStyle.value = window.initResponse.sectionNavigationStyle || 'sidebar' sectionNavigationStyle.value = window.initResponse.sectionNavigationStyle || 'sidebar'
availableThemes.value = window.initResponse.availableThemes || [] availableThemes.value = window.initResponse.availableThemes || []

View File

@ -162,7 +162,10 @@ async function generateBrowserInfo() {
userAgentData: userAgentData userAgentData: userAgentData
} }
const olivetinVersion = window.initResponse?.currentVersion || t('diagnostics.unknown') const showVersionNumber = window.initResponse?.effectivePolicy?.showVersionNumber ?? true
const olivetinVersion = showVersionNumber
? (window.initResponse?.currentVersion || t('diagnostics.unknown'))
: '[hidden]'
const currentLanguage = locale.value || t('diagnostics.unknown') const currentLanguage = locale.value || t('diagnostics.unknown')
let output = ''; let output = '';

View File

@ -0,0 +1,13 @@
#
# Integration Test Config: xterm link handling
#
listenAddressSingleHTTPFrontend: 0.0.0.0:1337
logLevel: "DEBUG"
checkForUpdates: false
actions:
- title: Echo URL
shell: echo "See https://example.com for more info"
popupOnStart: execution-dialog-stdout-only

View File

@ -0,0 +1,69 @@
import { describe, it, before, after } from 'mocha'
import { expect } from 'chai'
import { By, Condition } from 'selenium-webdriver'
import {
getRootAndWait,
takeScreenshotOnFailure,
getTerminalBuffer,
} from '../../lib/elements.js'
describe('config: xtermLinkHandling', function () {
before(async function () {
await runner.start('xtermLinkHandling')
})
after(async () => {
await runner.stop()
})
afterEach(function () {
takeScreenshotOnFailure(this.currentTest, webdriver)
})
it('xterm output shows URL and link handling is configured', async function () {
await getRootAndWait()
await webdriver.wait(new Condition('wait for Echo URL button', async () => {
const btns = await webdriver.findElements(By.css('[title="Echo URL"]'))
return btns.length === 1
}), 10000)
const echoUrlButton = await webdriver.findElement(By.css('[title="Echo URL"]'))
await echoUrlButton.click()
await webdriver.wait(new Condition('wait for execution view', async () => {
const url = await webdriver.getCurrentUrl()
return url.includes('/logs/') && !url.endsWith('/logs')
}), 10000)
await webdriver.wait(new Condition('wait for execution status', async () => {
const statusElements = await webdriver.findElements(By.id('execution-dialog-status'))
return statusElements.length > 0
}), 5000)
await webdriver.wait(new Condition('wait for execution to finish', async () => {
try {
const statusElement = await webdriver.findElement(By.id('execution-dialog-status'))
const statusText = await statusElement.getText()
return !statusText.includes('Executing')
} catch (e) {
return false
}
}), 5000)
await webdriver.sleep(500)
const bufferText = await getTerminalBuffer()
expect(bufferText).to.not.be.null
expect(bufferText).to.include('https://example.com')
const linkHandlerSet = await webdriver.executeScript(`
try {
return !!(window.terminal && window.terminal.linkHandlerConfigured === true)
} catch (e) {
return false
}
`)
expect(linkHandlerSet).to.equal(true)
})
})

View File

@ -51,6 +51,7 @@ message GetDashboardResponse {
message EffectivePolicy { message EffectivePolicy {
bool show_diagnostics = 1; bool show_diagnostics = 1;
bool show_log_list = 2; bool show_log_list = 2;
bool show_version_number = 3;
} }
message GetDashboardRequest { message GetDashboardRequest {

View File

@ -410,11 +410,12 @@ func (x *GetDashboardResponse) GetDashboard() *Dashboard {
} }
type EffectivePolicy struct { type EffectivePolicy struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
ShowDiagnostics bool `protobuf:"varint,1,opt,name=show_diagnostics,json=showDiagnostics,proto3" json:"show_diagnostics,omitempty"` ShowDiagnostics bool `protobuf:"varint,1,opt,name=show_diagnostics,json=showDiagnostics,proto3" json:"show_diagnostics,omitempty"`
ShowLogList bool `protobuf:"varint,2,opt,name=show_log_list,json=showLogList,proto3" json:"show_log_list,omitempty"` ShowLogList bool `protobuf:"varint,2,opt,name=show_log_list,json=showLogList,proto3" json:"show_log_list,omitempty"`
unknownFields protoimpl.UnknownFields ShowVersionNumber bool `protobuf:"varint,3,opt,name=show_version_number,json=showVersionNumber,proto3" json:"show_version_number,omitempty"`
sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
} }
func (x *EffectivePolicy) Reset() { func (x *EffectivePolicy) Reset() {
@ -461,6 +462,13 @@ func (x *EffectivePolicy) GetShowLogList() bool {
return false return false
} }
func (x *EffectivePolicy) GetShowVersionNumber() bool {
if x != nil {
return x.ShowVersionNumber
}
return false
}
type GetDashboardRequest struct { type GetDashboardRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"`
@ -3934,10 +3942,11 @@ const file_olivetin_api_v1_olivetin_proto_rawDesc = "" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"f\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"f\n" +
"\x14GetDashboardResponse\x12\x14\n" + "\x14GetDashboardResponse\x12\x14\n" +
"\x05title\x18\x01 \x01(\tR\x05title\x128\n" + "\x05title\x18\x01 \x01(\tR\x05title\x128\n" +
"\tdashboard\x18\x04 \x01(\v2\x1a.olivetin.api.v1.DashboardR\tdashboard\"`\n" + "\tdashboard\x18\x04 \x01(\v2\x1a.olivetin.api.v1.DashboardR\tdashboard\"\x90\x01\n" +
"\x0fEffectivePolicy\x12)\n" + "\x0fEffectivePolicy\x12)\n" +
"\x10show_diagnostics\x18\x01 \x01(\bR\x0fshowDiagnostics\x12\"\n" + "\x10show_diagnostics\x18\x01 \x01(\bR\x0fshowDiagnostics\x12\"\n" +
"\rshow_log_list\x18\x02 \x01(\bR\vshowLogList\"k\n" + "\rshow_log_list\x18\x02 \x01(\bR\vshowLogList\x12.\n" +
"\x13show_version_number\x18\x03 \x01(\bR\x11showVersionNumber\"k\n" +
"\x13GetDashboardRequest\x12\x14\n" + "\x13GetDashboardRequest\x12\x14\n" +
"\x05title\x18\x01 \x01(\tR\x05title\x12\x1f\n" + "\x05title\x18\x01 \x01(\tR\x05title\x12\x1f\n" +
"\ventity_type\x18\x02 \x01(\tR\n" + "\ventity_type\x18\x02 \x01(\tR\n" +

View File

@ -1,6 +1,6 @@
module github.com/OliveTin/OliveTin module github.com/OliveTin/OliveTin
go 1.25.0 go 1.25.6
exclude google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 exclude google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884
@ -10,7 +10,7 @@ require (
github.com/MicahParks/keyfunc/v3 v3.8.0 github.com/MicahParks/keyfunc/v3 v3.8.0
github.com/PaesslerAG/jsonpath v0.1.1 github.com/PaesslerAG/jsonpath v0.1.1
github.com/alexedwards/argon2id v1.0.0 github.com/alexedwards/argon2id v1.0.0
github.com/bufbuild/buf v1.65.0 github.com/bufbuild/buf v1.66.0
github.com/fsnotify/fsnotify v1.9.0 github.com/fsnotify/fsnotify v1.9.0
github.com/fzipp/gocyclo v0.6.0 github.com/fzipp/gocyclo v0.6.0
github.com/go-critic/go-critic v0.14.3 github.com/go-critic/go-critic v0.14.3
@ -27,7 +27,7 @@ require (
github.com/sirupsen/logrus v1.9.4 github.com/sirupsen/logrus v1.9.4
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
go.akshayshah.org/connectproto v0.6.0 go.akshayshah.org/connectproto v0.6.0
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa
golang.org/x/oauth2 v0.35.0 golang.org/x/oauth2 v0.35.0
golang.org/x/sys v0.41.0 golang.org/x/sys v0.41.0
google.golang.org/protobuf v1.36.11 google.golang.org/protobuf v1.36.11
@ -45,7 +45,7 @@ require (
buf.build/go/bufplugin v0.9.0 // indirect buf.build/go/bufplugin v0.9.0 // indirect
buf.build/go/bufprivateusage v0.1.0 // indirect buf.build/go/bufprivateusage v0.1.0 // indirect
buf.build/go/interrupt v1.1.0 // indirect buf.build/go/interrupt v1.1.0 // indirect
buf.build/go/protovalidate v1.1.2 // indirect buf.build/go/protovalidate v1.1.3 // indirect
buf.build/go/protoyaml v0.6.0 // indirect buf.build/go/protoyaml v0.6.0 // indirect
buf.build/go/spdx v0.2.0 // indirect buf.build/go/spdx v0.2.0 // indirect
buf.build/go/standard v0.1.0 // indirect buf.build/go/standard v0.1.0 // indirect
@ -57,7 +57,7 @@ require (
github.com/PaesslerAG/gval v1.2.4 // indirect github.com/PaesslerAG/gval v1.2.4 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bufbuild/protocompile v0.14.2-0.20260130195850-5c64bed4577e // indirect github.com/bufbuild/protocompile v0.14.2-0.20260202185951-d02d3732d113 // indirect
github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1 // indirect github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cli/browser v1.3.0 // indirect github.com/cli/browser v1.3.0 // indirect
@ -90,7 +90,7 @@ require (
github.com/gofrs/flock v0.13.0 // indirect github.com/gofrs/flock v0.13.0 // indirect
github.com/google/cel-go v0.27.0 // indirect github.com/google/cel-go v0.27.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-containerregistry v0.20.7 // indirect github.com/google/go-containerregistry v0.21.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jdx/go-netrc v1.0.0 // indirect github.com/jdx/go-netrc v1.0.0 // indirect
@ -155,8 +155,8 @@ require (
golang.org/x/text v0.34.0 // indirect golang.org/x/text v0.34.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.42.0 // indirect golang.org/x/tools v0.42.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect
google.golang.org/grpc v1.75.1 // indirect google.golang.org/grpc v1.75.1 // indirect
mvdan.cc/xurls/v2 v2.6.0 // indirect mvdan.cc/xurls/v2 v2.6.0 // indirect
pluginrpc.com/pluginrpc v0.5.0 // indirect pluginrpc.com/pluginrpc v0.5.0 // indirect

View File

@ -32,6 +32,8 @@ buf.build/go/protovalidate v1.1.0 h1:pQqEQRpOo4SqS60qkvmhLTTQU9JwzEvdyiqAtXa5SeY
buf.build/go/protovalidate v1.1.0/go.mod h1:bGZcPiAQDC3ErCHK3t74jSoJDFOs2JH3d7LWuTEIdss= buf.build/go/protovalidate v1.1.0/go.mod h1:bGZcPiAQDC3ErCHK3t74jSoJDFOs2JH3d7LWuTEIdss=
buf.build/go/protovalidate v1.1.2 h1:83vYHoY8f34hB8MeitGaYE3CGVPFxwdEUuskh5qQpA0= buf.build/go/protovalidate v1.1.2 h1:83vYHoY8f34hB8MeitGaYE3CGVPFxwdEUuskh5qQpA0=
buf.build/go/protovalidate v1.1.2/go.mod h1:Ez3z+w4c+wG+EpW8ovgZaZPnPl2XVF6kaxgcv1NG/QE= buf.build/go/protovalidate v1.1.2/go.mod h1:Ez3z+w4c+wG+EpW8ovgZaZPnPl2XVF6kaxgcv1NG/QE=
buf.build/go/protovalidate v1.1.3 h1:m2GVEgQWd7rk+vIoAZ+f0ygGjvQTuqPQapBBdcpWVPE=
buf.build/go/protovalidate v1.1.3/go.mod h1:9XIuohWz+kj+9JVn3WQneHA5LZP50mjvneZMnbLkiIE=
buf.build/go/protoyaml v0.6.0 h1:Nzz1lvcXF8YgNZXk+voPPwdU8FjDPTUV4ndNTXN0n2w= buf.build/go/protoyaml v0.6.0 h1:Nzz1lvcXF8YgNZXk+voPPwdU8FjDPTUV4ndNTXN0n2w=
buf.build/go/protoyaml v0.6.0/go.mod h1:RgUOsBu/GYKLDSIRgQXniXbNgFlGEZnQpRAUdLAFV2Q= buf.build/go/protoyaml v0.6.0/go.mod h1:RgUOsBu/GYKLDSIRgQXniXbNgFlGEZnQpRAUdLAFV2Q=
buf.build/go/spdx v0.2.0 h1:IItqM0/cMxvFJJumcBuP8NrsIzMs/UYjp/6WSpq8LTw= buf.build/go/spdx v0.2.0 h1:IItqM0/cMxvFJJumcBuP8NrsIzMs/UYjp/6WSpq8LTw=
@ -84,6 +86,8 @@ github.com/bufbuild/buf v1.64.0 h1:puHWFcVKmZFSu4KuaN0kZiQ32n7VVc3un1FeLU77XUs=
github.com/bufbuild/buf v1.64.0/go.mod h1:U4ISwkjZXRLMaCkPG9zp1xY3xHEIwhCFwyNAaA56SGw= github.com/bufbuild/buf v1.64.0/go.mod h1:U4ISwkjZXRLMaCkPG9zp1xY3xHEIwhCFwyNAaA56SGw=
github.com/bufbuild/buf v1.65.0 h1:f2BzeCY9rRh9P5KD340ZoPAaFLTkssoUTHx7lpqozgg= github.com/bufbuild/buf v1.65.0 h1:f2BzeCY9rRh9P5KD340ZoPAaFLTkssoUTHx7lpqozgg=
github.com/bufbuild/buf v1.65.0/go.mod h1:7SAs2YqGpPXHqBBXBeYQbCzY0OQq4Jbg6XCqirEiYvQ= github.com/bufbuild/buf v1.65.0/go.mod h1:7SAs2YqGpPXHqBBXBeYQbCzY0OQq4Jbg6XCqirEiYvQ=
github.com/bufbuild/buf v1.66.0 h1:6kksYJpu6r45bvPJSTwNSwRqiAjrwB9YyU7skjNzFVo=
github.com/bufbuild/buf v1.66.0/go.mod h1:tWVlwtIPZ7kzlCB9D0hbbfrroT0GNCybPdPQXq1i1Ac=
github.com/bufbuild/protocompile v0.14.2-0.20251223142729-db46c1b9d34e h1:LQA+1MyiPkolGHJGC2GMDC5Xu+0RDVH6jGMKech7Exs= github.com/bufbuild/protocompile v0.14.2-0.20251223142729-db46c1b9d34e h1:LQA+1MyiPkolGHJGC2GMDC5Xu+0RDVH6jGMKech7Exs=
github.com/bufbuild/protocompile v0.14.2-0.20251223142729-db46c1b9d34e/go.mod h1:5UUj46Eu+U+C59C5N6YilaMI7WWfP2bW9xGcOkme2DI= github.com/bufbuild/protocompile v0.14.2-0.20251223142729-db46c1b9d34e/go.mod h1:5UUj46Eu+U+C59C5N6YilaMI7WWfP2bW9xGcOkme2DI=
github.com/bufbuild/protocompile v0.14.2-0.20260105175043-4d8d90b1c6b8 h1:cQYwUyAzyMmYr7AyJU1C6pVCpUrJJBkmx7UunZosxxs= github.com/bufbuild/protocompile v0.14.2-0.20260105175043-4d8d90b1c6b8 h1:cQYwUyAzyMmYr7AyJU1C6pVCpUrJJBkmx7UunZosxxs=
@ -92,6 +96,8 @@ github.com/bufbuild/protocompile v0.14.2-0.20260120135352-a3ed5cd7a608 h1:3aRREB
github.com/bufbuild/protocompile v0.14.2-0.20260120135352-a3ed5cd7a608/go.mod h1:5UUj46Eu+U+C59C5N6YilaMI7WWfP2bW9xGcOkme2DI= github.com/bufbuild/protocompile v0.14.2-0.20260120135352-a3ed5cd7a608/go.mod h1:5UUj46Eu+U+C59C5N6YilaMI7WWfP2bW9xGcOkme2DI=
github.com/bufbuild/protocompile v0.14.2-0.20260130195850-5c64bed4577e h1:emH16Bf1w4C0cJ3ge4QtBAl4sIYJe23EfpWH0SpA9co= github.com/bufbuild/protocompile v0.14.2-0.20260130195850-5c64bed4577e h1:emH16Bf1w4C0cJ3ge4QtBAl4sIYJe23EfpWH0SpA9co=
github.com/bufbuild/protocompile v0.14.2-0.20260130195850-5c64bed4577e/go.mod h1:cxhE8h+14t0Yxq2H9MV/UggzQ1L0gh0t2tJobITWsBE= github.com/bufbuild/protocompile v0.14.2-0.20260130195850-5c64bed4577e/go.mod h1:cxhE8h+14t0Yxq2H9MV/UggzQ1L0gh0t2tJobITWsBE=
github.com/bufbuild/protocompile v0.14.2-0.20260202185951-d02d3732d113 h1:nxt1QhP9rMQNFhHTdcNFwJ9wKCSdBjd28gz+qGDv4kM=
github.com/bufbuild/protocompile v0.14.2-0.20260202185951-d02d3732d113/go.mod h1:cxhE8h+14t0Yxq2H9MV/UggzQ1L0gh0t2tJobITWsBE=
github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1 h1:V1xulAoqLqVg44rY97xOR+mQpD2N+GzhMHVwJ030WEU= github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1 h1:V1xulAoqLqVg44rY97xOR+mQpD2N+GzhMHVwJ030WEU=
github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1/go.mod h1:c5D8gWRIZ2HLWO3gXYTtUfw/hbJyD8xikv2ooPxnklQ= github.com/bufbuild/protoplugin v0.0.0-20250218205857-750e09ce93e1/go.mod h1:c5D8gWRIZ2HLWO3gXYTtUfw/hbJyD8xikv2ooPxnklQ=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
@ -200,6 +206,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-containerregistry v0.20.7 h1:24VGNpS0IwrOZ2ms2P1QE3Xa5X9p4phx0aUgzYzHW6I= github.com/google/go-containerregistry v0.20.7 h1:24VGNpS0IwrOZ2ms2P1QE3Xa5X9p4phx0aUgzYzHW6I=
github.com/google/go-containerregistry v0.20.7/go.mod h1:Lx5LCZQjLH1QBaMPeGwsME9biPeo1lPx6lbGj/UmzgM= github.com/google/go-containerregistry v0.20.7/go.mod h1:Lx5LCZQjLH1QBaMPeGwsME9biPeo1lPx6lbGj/UmzgM=
github.com/google/go-containerregistry v0.21.0 h1:ocqxUOczFwAZQBMNE7kuzfqvDe0VWoZxQMOesXreCDI=
github.com/google/go-containerregistry v0.21.0/go.mod h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
@ -375,6 +383,7 @@ go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIl
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
@ -421,6 +430,8 @@ golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a h1:ovFr6Z0MNmU7nH8VaX5xqw+05ST2uO1exVfZPVqRC5o= golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a h1:ovFr6Z0MNmU7nH8VaX5xqw+05ST2uO1exVfZPVqRC5o=
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA= golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20251219203646-944ab1f22d93 h1:PbC785RGO6yPO051ItgbG/adwoKRWC0VS7kXXeD/iqk= golang.org/x/exp/typeparams v0.0.0-20251219203646-944ab1f22d93 h1:PbC785RGO6yPO051ItgbG/adwoKRWC0VS7kXXeD/iqk=
@ -519,6 +530,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260122232226-8e98ce8d340d h1:
google.golang.org/genproto/googleapis/api v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw= google.golang.org/genproto/googleapis/api v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw=
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0= google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY= google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d h1:EocjzKLywydp5uZ5tJ79iP6Q0UjDnyiHkGRWxuPBP8s=
google.golang.org/genproto/googleapis/api v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:48U2I+QQUYhsFrg2SY6r+nJzeOtjey7j//WBESw+qyQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU=
@ -527,6 +540,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=

View File

@ -710,7 +710,9 @@ func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *connect.Request[apiv1.WhoAm
} }
func (api *oliveTinAPI) SosReport(ctx ctx.Context, req *connect.Request[apiv1.SosReportRequest]) (*connect.Response[apiv1.SosReportResponse], error) { func (api *oliveTinAPI) SosReport(ctx ctx.Context, req *connect.Request[apiv1.SosReportRequest]) (*connect.Response[apiv1.SosReportResponse], error) {
sos := installationinfo.GetSosReport() user := auth.UserFromApiCall(ctx, req, api.cfg)
redactVersion := !user.EffectivePolicy.ShowVersionNumber
sos := installationinfo.GetSosReport(redactVersion)
if !api.cfg.InsecureAllowDumpSos { if !api.cfg.InsecureAllowDumpSos {
log.Info(sos) log.Info(sos)
@ -914,12 +916,19 @@ func (api *oliveTinAPI) Init(ctx ctx.Context, req *connect.Request[apiv1.InitReq
loginRequired := user.IsGuest() && api.cfg.AuthRequireGuestsToLogin loginRequired := user.IsGuest() && api.cfg.AuthRequireGuestsToLogin
showVersion := user.EffectivePolicy.ShowVersionNumber
currentVersion := ""
availableVersion := ""
if showVersion {
currentVersion = installationinfo.Build.Version
availableVersion = installationinfo.Runtime.AvailableVersion
}
res := &apiv1.InitResponse{ res := &apiv1.InitResponse{
ShowFooter: api.cfg.ShowFooter, ShowFooter: api.cfg.ShowFooter,
ShowNavigation: api.cfg.ShowNavigation, ShowNavigation: api.cfg.ShowNavigation,
ShowNewVersions: api.cfg.ShowNewVersions, ShowNewVersions: showVersion && api.cfg.ShowNewVersions,
AvailableVersion: installationinfo.Runtime.AvailableVersion, AvailableVersion: availableVersion,
CurrentVersion: installationinfo.Build.Version, CurrentVersion: currentVersion,
PageTitle: api.cfg.PageTitle, PageTitle: api.cfg.PageTitle,
SectionNavigationStyle: api.cfg.SectionNavigationStyle, SectionNavigationStyle: api.cfg.SectionNavigationStyle,
DefaultIconForBack: api.cfg.DefaultIconForBack, DefaultIconForBack: api.cfg.DefaultIconForBack,

View File

@ -55,8 +55,9 @@ func matchesEntity(binding *executor.ActionBinding, entity *entities.Entity) boo
func buildEffectivePolicy(policy *config.ConfigurationPolicy) *apiv1.EffectivePolicy { func buildEffectivePolicy(policy *config.ConfigurationPolicy) *apiv1.EffectivePolicy {
ret := &apiv1.EffectivePolicy{ ret := &apiv1.EffectivePolicy{
ShowDiagnostics: policy.ShowDiagnostics, ShowDiagnostics: policy.ShowDiagnostics,
ShowLogList: policy.ShowLogList, ShowLogList: policy.ShowLogList,
ShowVersionNumber: policy.ShowVersionNumber,
} }
return ret return ret

View File

@ -76,8 +76,9 @@ func (u *AuthenticatedUser) BuildUserAcls(cfg *config.Config) {
func getEffectivePolicy(cfg *config.Config, u *AuthenticatedUser) *config.ConfigurationPolicy { func getEffectivePolicy(cfg *config.Config, u *AuthenticatedUser) *config.ConfigurationPolicy {
ret := &config.ConfigurationPolicy{ ret := &config.ConfigurationPolicy{
ShowDiagnostics: cfg.DefaultPolicy.ShowDiagnostics, ShowDiagnostics: cfg.DefaultPolicy.ShowDiagnostics,
ShowLogList: cfg.DefaultPolicy.ShowLogList, ShowLogList: cfg.DefaultPolicy.ShowLogList,
ShowVersionNumber: cfg.DefaultPolicy.ShowVersionNumber,
} }
for _, acl := range cfg.AccessControlLists { for _, acl := range cfg.AccessControlLists {
@ -98,5 +99,9 @@ func buildConfigurationPolicy(ret *config.ConfigurationPolicy, policy config.Con
ret.ShowLogList = policy.ShowLogList ret.ShowLogList = policy.ShowLogList
} }
if policy.ShowVersionNumber {
ret.ShowVersionNumber = policy.ShowVersionNumber
}
return ret return ret
} }

View File

@ -11,6 +11,7 @@ import (
"io" "io"
"net/http" "net/http"
"os" "os"
"sync"
"time" "time"
authTypes "github.com/OliveTin/OliveTin/internal/auth/authpublic" authTypes "github.com/OliveTin/OliveTin/internal/auth/authpublic"
@ -21,6 +22,7 @@ import (
type OAuth2Handler struct { type OAuth2Handler struct {
cfg *config.Config cfg *config.Config
mu sync.RWMutex
registeredStates map[string]*oauth2State registeredStates map[string]*oauth2State
registeredProviders map[string]*oauth2.Config registeredProviders map[string]*oauth2.Config
} }
@ -144,11 +146,13 @@ func (h *OAuth2Handler) HandleOAuthLogin(w http.ResponseWriter, r *http.Request)
return return
} }
h.mu.Lock()
h.registeredStates[state] = &oauth2State{ h.registeredStates[state] = &oauth2State{
providerConfig: provider, providerConfig: provider,
providerName: providerName, providerName: providerName,
Username: "", Username: "",
} }
h.mu.Unlock()
h.setOAuthCallbackCookie(w, r, "olivetin-sid-oauth", state) h.setOAuthCallbackCookie(w, r, "olivetin-sid-oauth", state)
@ -177,7 +181,9 @@ func (h *OAuth2Handler) checkOAuthCallbackCookie(w http.ResponseWriter, r *http.
return nil, state, false return nil, state, false
} }
h.mu.RLock()
registeredState, ok := h.registeredStates[state] registeredState, ok := h.registeredStates[state]
h.mu.RUnlock()
if !ok { if !ok {
log.Errorf("State not found in server: %v", state) log.Errorf("State not found in server: %v", state)
http.Error(w, "State not found in server", http.StatusBadRequest) http.Error(w, "State not found in server", http.StatusBadRequest)
@ -287,8 +293,10 @@ func (h *OAuth2Handler) HandleOAuthCallback(w http.ResponseWriter, r *http.Reque
userInfoClient := h.createUserInfoClient(ctx, registeredState.providerConfig, tok, clientSettings) userInfoClient := h.createUserInfoClient(ctx, registeredState.providerConfig, tok, clientSettings)
userinfo := getUserInfo(h.cfg, userInfoClient, providerConfig) userinfo := getUserInfo(h.cfg, userInfoClient, providerConfig)
h.mu.Lock()
h.registeredStates[state].Username = userinfo.Username h.registeredStates[state].Username = userinfo.Username
h.registeredStates[state].Usergroup = h.computeUsergroup(userinfo, providerConfig) h.registeredStates[state].Usergroup = h.computeUsergroup(userinfo, providerConfig)
h.mu.Unlock()
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} }
@ -366,34 +374,36 @@ func getDataField(data map[string]any, field string) string {
return stringVal return stringVal
} }
func (h *OAuth2Handler) lookupOAuth2UserByState(state string) (*authTypes.AuthenticatedUser, bool) {
h.mu.RLock()
serverState, found := h.registeredStates[state]
if !found {
h.mu.RUnlock()
return nil, false
}
user := &authTypes.AuthenticatedUser{
Username: serverState.Username,
UsergroupLine: serverState.Usergroup,
Provider: "oauth2",
SID: state,
}
h.mu.RUnlock()
return user, true
}
func (h *OAuth2Handler) CheckUserFromOAuth2Cookie(context *authTypes.AuthCheckingContext) *authTypes.AuthenticatedUser { func (h *OAuth2Handler) CheckUserFromOAuth2Cookie(context *authTypes.AuthCheckingContext) *authTypes.AuthenticatedUser {
cookie, err := context.Request.Cookie("olivetin-sid-oauth") cookie, err := context.Request.Cookie("olivetin-sid-oauth")
if err != nil || cookie.Value == "" {
user := &authTypes.AuthenticatedUser{}
if err != nil {
return nil return nil
} }
if cookie.Value == "" { user, found := h.lookupOAuth2UserByState(cookie.Value)
return nil
}
serverState, found := h.registeredStates[cookie.Value]
if !found { if !found {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"sid": cookie.Value, "sid": cookie.Value,
"provider": "oauth2", "provider": "oauth2",
}).Warnf("Stale session") }).Warnf("Stale session")
return nil return nil
} }
user.Username = serverState.Username
user.UsergroupLine = serverState.Usergroup
user.Provider = "oauth2"
user.SID = cookie.Value
return user return user
} }

View File

@ -98,8 +98,9 @@ type AccessControlList struct {
// ConfigurationPolicy defines global settings which are overridden with an ACL. // ConfigurationPolicy defines global settings which are overridden with an ACL.
type ConfigurationPolicy struct { type ConfigurationPolicy struct {
ShowDiagnostics bool `koanf:"showDiagnostics"` ShowDiagnostics bool `koanf:"showDiagnostics"`
ShowLogList bool `koanf:"showLogList"` ShowLogList bool `koanf:"showLogList"`
ShowVersionNumber bool `koanf:"showVersionNumber"`
} }
type PrometheusConfig struct { type PrometheusConfig struct {
@ -297,6 +298,7 @@ func DefaultConfigWithBasePort(basePort int) *Config {
config.DefaultPolicy.ShowDiagnostics = true config.DefaultPolicy.ShowDiagnostics = true
config.DefaultPolicy.ShowLogList = true config.DefaultPolicy.ShowLogList = true
config.DefaultPolicy.ShowVersionNumber = true
return &config return &config
} }

View File

@ -164,6 +164,7 @@ func (cfg *Config) sanitizeAuthRequireGuestsToLogin() {
cfg.DefaultPermissions.View = false cfg.DefaultPermissions.View = false
cfg.DefaultPermissions.Exec = false cfg.DefaultPermissions.Exec = false
cfg.DefaultPermissions.Logs = false cfg.DefaultPermissions.Logs = false
cfg.DefaultPermissions.Kill = false
} }
} }

View File

@ -40,15 +40,23 @@ func configToSosreport(cfg *config.Config) *sosReportConfig {
} }
} }
func GetSosReport() string { func GetSosReport(redactVersion bool) string {
ret := "" ret := ""
ret += "### SOSREPORT START (copy all text to SOSREPORT END)\n" ret += "### SOSREPORT START (copy all text to SOSREPORT END)\n"
out, _ := yaml.Marshal(Build) buildForReport := *Build
if redactVersion {
buildForReport.Version = "[redacted]"
}
out, _ := yaml.Marshal(&buildForReport)
ret += fmt.Sprintf("# Build: \n%+v\n", string(out)) ret += fmt.Sprintf("# Build: \n%+v\n", string(out))
out, _ = yaml.Marshal(Runtime) runtimeForReport := *Runtime
if redactVersion {
runtimeForReport.AvailableVersion = "[redacted]"
}
out, _ = yaml.Marshal(&runtimeForReport)
ret += fmt.Sprintf("# Runtime:\n%+v\n", string(out)) ret += fmt.Sprintf("# Runtime:\n%+v\n", string(out))
out, _ = yaml.Marshal(configToSosreport(Config)) out, _ = yaml.Marshal(configToSosreport(Config))