jojo/modules/setting/actions_test.go

237 lines
6.4 KiB
Go
Raw Permalink Normal View History

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"path/filepath"
"testing"
feat: add OIDC workload identity federation support (#10481) Add support for OIDC workload identity federation. Add ID_TOKEN_SIGNING_ALGORITHM, ID_TOKEN_SIGNING_PRIVATE_KEY_FILE, and ID_TOKEN_EXPIRATION_TIME settings to settings.actions to allow for admin configuration of this functionality. Add OIDC endpoints (/.well-known/openid-configuration and /.well-known/keys) underneath the "/api/actions" route. Add a token generation endpoint (/_apis/pipelines/workflows/{run_id}/idtoken) underneath the "/api/actions" route. Depends on: https://code.forgejo.org/forgejo/runner/pulls/1232 Docs PR: https://codeberg.org/forgejo/docs/pulls/1667 Signed-off-by: Mario Minardi <mminardi@shaw.ca> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10481 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Mario Minardi <mminardi@shaw.ca> Co-committed-by: Mario Minardi <mminardi@shaw.ca>
2026-01-15 03:39:00 +01:00
"forgejo.org/modules/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_getStorageInheritNameSectionTypeForActions(t *testing.T) {
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
iniStr = `
[storage.actions_log]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
iniStr = `
[storage.actions_log]
STORAGE_TYPE = my_storage
[storage.my_storage]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.Equal(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
iniStr = `
[storage.actions_artifacts]
STORAGE_TYPE = my_storage
[storage.my_storage]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "local", Actions.LogStorage.Type)
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
iniStr = `
[storage.actions_artifacts]
STORAGE_TYPE = my_storage
[storage.my_storage]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "local", Actions.LogStorage.Type)
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.Equal(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
iniStr = ``
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "local", Actions.LogStorage.Type)
assert.Equal(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
assert.Equal(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
}
func Test_getDefaultActionsURLForActions(t *testing.T) {
oldActions := Actions
oldAppURL := AppURL
defer func() {
Actions = oldActions
AppURL = oldAppURL
}()
AppURL = "http://test_get_default_actions_url_for_actions:3000/"
tests := []struct {
name string
iniStr string
wantURL string
}{
{
name: "default",
iniStr: `
[actions]
`,
wantURL: "https://data.forgejo.org",
},
{
name: "github",
iniStr: `
[actions]
DEFAULT_ACTIONS_URL = github
`,
wantURL: "https://github.com",
},
{
name: "self",
iniStr: `
[actions]
DEFAULT_ACTIONS_URL = self
`,
wantURL: "http://test_get_default_actions_url_for_actions:3000",
},
{
name: "custom urls",
iniStr: `
[actions]
[CI] DEFAULT_ACTIONS_URL = https://code.forgejo.org [CI] Revert "Restrict `[actions].DEFAULT_ACTIONS_URL` to only `github` or `self` (#25581)" This reverts commit 67bd9d4f1eedb4728031504d0dd09d014c0f3e6f. (cherry picked from commit 0547e94023a545fafe82e280dd809e7efd6d86e2) (cherry picked from commit d21ad654ad0abc243913532326e916899b0e387c) (cherry picked from commit b905e9d8386c58206234a417769cc17b3be34b62) (cherry picked from commit 251a5bf235b1723bc2bc324f9e8c03a8668bb5ae) (cherry picked from commit b370e4769423bec92b0f265f3e3b2b683640024d) (cherry picked from commit 2cc28d078507027749c14a5448e949ab54b79c66) (cherry picked from commit ed870a39e98fbb69c435a3a3ef0434fe6163ebe7) (cherry picked from commit 7bb0c4654ecbbd2feee2c74034c1e2cdca0d6828) (cherry picked from commit bab1f552c385e3c7d0faa33d28fb8087780ea834) Conflicts: custom/conf/app.example.ini modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1413 [CI] DEFAULT_ACTIONS_URL = https://codeberg.org (cherry picked from commit 52b364ddbd9ac82b9e6f9c1767db2d6b36165011) (cherry picked from commit 99887cd5673f6da49664b590ad60c83fdbe25a4a) (cherry picked from commit cd5788782aa5c2ee8baecd57ca1e7882f0854453) (cherry picked from commit 71c698a704d307c568f247710550d48f27cca4ce) (cherry picked from commit 71386241dd741a4fa0b67d59a07d84ac31e0b870) (cherry picked from commit b7ab05aeac12c44acd117d5a4e8d7b4da2ba4aa7) (cherry picked from commit e78b9ca59c0af867f94d9c9bfae48f8cc9381224) (cherry picked from commit edb3adf4606af94ed0ab0bd844ef626a39a99297) (cherry picked from commit 3e400881975340be9148c4549a744395a6dac665) [BRANDING] DEFAULT_ACTIONS_URL = https://code.forgejo.org (cherry picked from commit d0e4512c902dec669da36a055a2ea54adb107e0f) (cherry picked from commit 8ba6e047095e9ecb107d77361664fa83b03ddaa2) (cherry picked from commit 63490810449b4189ed8538a22182fde1bc89c057) (cherry picked from commit e06bd444951d1fd94a71ce3d591a8f397f456363) (cherry picked from commit d58219d8e13f0b4007108d78f8f6f96a1d842c2c) (cherry picked from commit 052f2c2aa45ae1aa1d59aaf713db4f771f62773b) (cherry picked from commit 29dc39538631f65eaaf5dcc4eeb747fbc68d7498) (cherry picked from commit 9eef3f59f3a1347ccc7d6d3704c9f5b40a3b6555) (cherry picked from commit d650391fedd5b2cac313e29d51cc8689d885a594) (cherry picked from commit c2e6e8c55d955f1e2b781c983f05319dddcc4386) (cherry picked from commit e28a47741dc668421989b6b2310365a6611b23b7) [CI] DEFAULT_ACTIONS_URL support for self & github (squash) Refs: https://codeberg.org/forgejo/forgejo/issues/1062 (cherry picked from commit 74cc25376ecd1dbab57abffe286ae1f918057cfd) (cherry picked from commit 405430708ffbebcfd2cefdcdfd24a540985b817c) (cherry picked from commit 0274a6dee7f383bcd6b65b995b991b5ab0ee635a) (cherry picked from commit be5cda0fd03b265367c551aefed83456be257075) (cherry picked from commit d27474849fc4dd4ec958c04b7be06eced8b74d6e) (cherry picked from commit 4a5e9e2d81f89b5c9e6782d1c24880d62f802d7f) (cherry picked from commit 65b31906b27c7a6ecaecf74af748e046c51aa7a8) (cherry picked from commit 13cf0b0963bb110db7229dc5cd4d202e7dec11fb) Conflicts: custom/conf/app.example.ini modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1413 (cherry picked from commit 49529badce0a43a07a786b22e2a8705a6a1dbe63) Conflicts: custom/conf/app.example.ini docs/content/administration/config-cheat-sheet.en-us.md modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1460 (cherry picked from commit 00327b9b1f8512ddb93a07b57fcaee53b701478b) (cherry picked from commit 3b322e43d5695d540a52259abdde74505241dda9) (cherry picked from commit 492cc5205908263a2733ba06a6562237406d4c11) Conflicts: modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1573 (cherry picked from commit 9027b655df24bf47f49cc25d3547b6e49f66dde5) (cherry picked from commit 47643830286025dbff1538e9a6ffc23b05ea3e4b) (cherry picked from commit fbb00fd1cf9ecf30292aa3053f41076d7bb9027e) (cherry picked from commit 417cd6c801bb14b38f672fea3371486c12636ebf) (cherry picked from commit 6b70773ad817f6f3958e958a58c3d918e7d7f00e) (cherry picked from commit 9ba069327d0c5179bdae7e22ca580f3c460e9ac1) Conflicts: modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1827 (cherry picked from commit 727edf19ee48648d1464f3bb38f85d82900870fa) (cherry picked from commit 689326ce2093701e57371759eda23ed9b7781286) (cherry picked from commit 745d60aec426e40a8ac98199e5f342113b39b871) (cherry picked from commit cb4ae4582c24552167e692871e697cc02384c054) (cherry picked from commit 48d5ffe1c0345f612e96acb2459c80431fa94993) Conflicts: custom/conf/app.example.ini https://codeberg.org/forgejo/forgejo/pulls/2068 (cherry picked from commit bbd4725bfdd82aa801ec0541c7dbdef9b39dcb1d) (cherry picked from commit 04eda91d10889febaee3f1b824defb2c0c9fb493) (cherry picked from commit d3621e46349645ad5e194ba6a21d4f607c403c8c) (cherry picked from commit 08da63cc4daacabf53ed18f4e521375b49bea8fe) (cherry picked from commit dc6d291b7127e92ae05bb51c6ae018734fbc3fc7)
2023-07-03 09:45:12 +02:00
DEFAULT_ACTIONS_URL = https://example.com
`,
[CI] DEFAULT_ACTIONS_URL = https://code.forgejo.org [CI] Revert "Restrict `[actions].DEFAULT_ACTIONS_URL` to only `github` or `self` (#25581)" This reverts commit 67bd9d4f1eedb4728031504d0dd09d014c0f3e6f. (cherry picked from commit 0547e94023a545fafe82e280dd809e7efd6d86e2) (cherry picked from commit d21ad654ad0abc243913532326e916899b0e387c) (cherry picked from commit b905e9d8386c58206234a417769cc17b3be34b62) (cherry picked from commit 251a5bf235b1723bc2bc324f9e8c03a8668bb5ae) (cherry picked from commit b370e4769423bec92b0f265f3e3b2b683640024d) (cherry picked from commit 2cc28d078507027749c14a5448e949ab54b79c66) (cherry picked from commit ed870a39e98fbb69c435a3a3ef0434fe6163ebe7) (cherry picked from commit 7bb0c4654ecbbd2feee2c74034c1e2cdca0d6828) (cherry picked from commit bab1f552c385e3c7d0faa33d28fb8087780ea834) Conflicts: custom/conf/app.example.ini modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1413 [CI] DEFAULT_ACTIONS_URL = https://codeberg.org (cherry picked from commit 52b364ddbd9ac82b9e6f9c1767db2d6b36165011) (cherry picked from commit 99887cd5673f6da49664b590ad60c83fdbe25a4a) (cherry picked from commit cd5788782aa5c2ee8baecd57ca1e7882f0854453) (cherry picked from commit 71c698a704d307c568f247710550d48f27cca4ce) (cherry picked from commit 71386241dd741a4fa0b67d59a07d84ac31e0b870) (cherry picked from commit b7ab05aeac12c44acd117d5a4e8d7b4da2ba4aa7) (cherry picked from commit e78b9ca59c0af867f94d9c9bfae48f8cc9381224) (cherry picked from commit edb3adf4606af94ed0ab0bd844ef626a39a99297) (cherry picked from commit 3e400881975340be9148c4549a744395a6dac665) [BRANDING] DEFAULT_ACTIONS_URL = https://code.forgejo.org (cherry picked from commit d0e4512c902dec669da36a055a2ea54adb107e0f) (cherry picked from commit 8ba6e047095e9ecb107d77361664fa83b03ddaa2) (cherry picked from commit 63490810449b4189ed8538a22182fde1bc89c057) (cherry picked from commit e06bd444951d1fd94a71ce3d591a8f397f456363) (cherry picked from commit d58219d8e13f0b4007108d78f8f6f96a1d842c2c) (cherry picked from commit 052f2c2aa45ae1aa1d59aaf713db4f771f62773b) (cherry picked from commit 29dc39538631f65eaaf5dcc4eeb747fbc68d7498) (cherry picked from commit 9eef3f59f3a1347ccc7d6d3704c9f5b40a3b6555) (cherry picked from commit d650391fedd5b2cac313e29d51cc8689d885a594) (cherry picked from commit c2e6e8c55d955f1e2b781c983f05319dddcc4386) (cherry picked from commit e28a47741dc668421989b6b2310365a6611b23b7) [CI] DEFAULT_ACTIONS_URL support for self & github (squash) Refs: https://codeberg.org/forgejo/forgejo/issues/1062 (cherry picked from commit 74cc25376ecd1dbab57abffe286ae1f918057cfd) (cherry picked from commit 405430708ffbebcfd2cefdcdfd24a540985b817c) (cherry picked from commit 0274a6dee7f383bcd6b65b995b991b5ab0ee635a) (cherry picked from commit be5cda0fd03b265367c551aefed83456be257075) (cherry picked from commit d27474849fc4dd4ec958c04b7be06eced8b74d6e) (cherry picked from commit 4a5e9e2d81f89b5c9e6782d1c24880d62f802d7f) (cherry picked from commit 65b31906b27c7a6ecaecf74af748e046c51aa7a8) (cherry picked from commit 13cf0b0963bb110db7229dc5cd4d202e7dec11fb) Conflicts: custom/conf/app.example.ini modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1413 (cherry picked from commit 49529badce0a43a07a786b22e2a8705a6a1dbe63) Conflicts: custom/conf/app.example.ini docs/content/administration/config-cheat-sheet.en-us.md modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1460 (cherry picked from commit 00327b9b1f8512ddb93a07b57fcaee53b701478b) (cherry picked from commit 3b322e43d5695d540a52259abdde74505241dda9) (cherry picked from commit 492cc5205908263a2733ba06a6562237406d4c11) Conflicts: modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1573 (cherry picked from commit 9027b655df24bf47f49cc25d3547b6e49f66dde5) (cherry picked from commit 47643830286025dbff1538e9a6ffc23b05ea3e4b) (cherry picked from commit fbb00fd1cf9ecf30292aa3053f41076d7bb9027e) (cherry picked from commit 417cd6c801bb14b38f672fea3371486c12636ebf) (cherry picked from commit 6b70773ad817f6f3958e958a58c3d918e7d7f00e) (cherry picked from commit 9ba069327d0c5179bdae7e22ca580f3c460e9ac1) Conflicts: modules/setting/actions.go https://codeberg.org/forgejo/forgejo/pulls/1827 (cherry picked from commit 727edf19ee48648d1464f3bb38f85d82900870fa) (cherry picked from commit 689326ce2093701e57371759eda23ed9b7781286) (cherry picked from commit 745d60aec426e40a8ac98199e5f342113b39b871) (cherry picked from commit cb4ae4582c24552167e692871e697cc02384c054) (cherry picked from commit 48d5ffe1c0345f612e96acb2459c80431fa94993) Conflicts: custom/conf/app.example.ini https://codeberg.org/forgejo/forgejo/pulls/2068 (cherry picked from commit bbd4725bfdd82aa801ec0541c7dbdef9b39dcb1d) (cherry picked from commit 04eda91d10889febaee3f1b824defb2c0c9fb493) (cherry picked from commit d3621e46349645ad5e194ba6a21d4f607c403c8c) (cherry picked from commit 08da63cc4daacabf53ed18f4e521375b49bea8fe) (cherry picked from commit dc6d291b7127e92ae05bb51c6ae018734fbc3fc7)
2023-07-03 09:45:12 +02:00
wantURL: "https://example.com",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg, err := NewConfigProviderFromData(tt.iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
assert.Equal(t, tt.wantURL, Actions.DefaultActionsURL.URL())
})
}
}
feat: add OIDC workload identity federation support (#10481) Add support for OIDC workload identity federation. Add ID_TOKEN_SIGNING_ALGORITHM, ID_TOKEN_SIGNING_PRIVATE_KEY_FILE, and ID_TOKEN_EXPIRATION_TIME settings to settings.actions to allow for admin configuration of this functionality. Add OIDC endpoints (/.well-known/openid-configuration and /.well-known/keys) underneath the "/api/actions" route. Add a token generation endpoint (/_apis/pipelines/workflows/{run_id}/idtoken) underneath the "/api/actions" route. Depends on: https://code.forgejo.org/forgejo/runner/pulls/1232 Docs PR: https://codeberg.org/forgejo/docs/pulls/1667 Signed-off-by: Mario Minardi <mminardi@shaw.ca> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10481 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Mario Minardi <mminardi@shaw.ca> Co-committed-by: Mario Minardi <mminardi@shaw.ca>
2026-01-15 03:39:00 +01:00
func Test_getIDTokenSettingsForActions(t *testing.T) {
defer test.MockVariableValue(&AppDataPath, "/home/app/data")()
oldActions := Actions
oldAppURL := AppURL
defer func() {
Actions = oldActions
AppURL = oldAppURL
}()
iniStr := `
[actions]
`
cfg, err := NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
chore: unify signing key configuration across modules (#11194) ## Context the three commits in this series are the first step towards the goal of removing the special casing around `JWT_SECRET`, which is used for various modules via `GetGeneralTokenSigningSecret()`. Ultimately, I want to work towards enabling seamless migration away from general use of the common secret. To enable this, we need proper secret/key rotation support, that is, we need to allow for configuration of additional secrets/keys which are accepted for token validation, but not used to issue tokens. I have this _Verifier_ support basically implemented, but this PR is not it. This PR contains cleanup refactoring which I worked on before writing the _Verifier_ support, because I noticed that the existing secret/key handling across modules was inconsistent and required duplicated code. I am submitting this part now to allow for incremental review of not too large a diff, and because these commits remained unchanged during two weeks since I moved on the the next task. ## The problem being addressed Configuration of JWT signing secrets/keys was inconsistent: Under `[oauth2]` the full configuration set was supported: - `JWT_SIGNING_ALGORITHM` configured the algorithm - `JWT_SECRET` configured a literal secret for symmetric algorithms - `JWT_SECRET_URI` configured a `file:` uri of a secret for symmetric algorithms - `JWT_SIGNING_PRIVATE_KEY_FILE` configured a file for asymmetric algorithms For `[server]`, the LFS module only supported `LFS_JWT_SECRET`, and the signing method was hardcoded to `HS256` For `[actions]`, only asymmetric signing methods were supported via `ID_TOKEN_SIGNING_ALGORITHM` and `ID_TOKEN_SIGNING_PRIVATE_KEY_FILE`. ## ini unification The proposed code centralizes ini parsing to always support the following ini keys: - `[pfx]SIGNING_ALGORITHM` determines the algorithm - `[pfx]SECRET` is a literal secret for symmetric algorithms - `[pfx]SECRET_URI` is the uri of a secret for symmetric algorithms - `[pfx]SIGNING_PRIVATE_KEY_FILE` is a file with a private key for asymmetric algorithms `[pfx]` is specific to the module and chosen to support the existing ini keys Centralizing this code and unifying the ini keys will come handy for at least the following reasons: - consistent behavior across modules is easier to understand - less duplicated code - easier to expand later, which is my main motivation ## implementation notes as might be apparent by the _take3_ branch name, this is the third iteration of this patch series. The main reason why I abandoned the other two is that I first tried to move all the key initialization into the code called from settings.go when the ini file is parsed. But that lead to a lot of friction with test cases, because private key files which are configured, but do not exist will get created and hence require a writable `AppDataPath` and additional clean up. To avoid a lot of noise and complications in test cases, I kept the existing two stage process, where - the settings component creates missing symmetric signing keys and writes them to the .ini - the settings component creates a simple configuration struct - which is then used from the module init to create the actual key, which also includes creating a private key file if asymmetric crypto is configured and the key file does not exist. I would have wished this patch was a net negative in terms of LOCs, but I hope it contributes to clarity and many added lines are in test cases. ## Commits Because sometimes PRs are merged as squashes with the PR text remaining, I am repeating here the individual messages of the individual commits for future reference: ### Refactor signing key initalization and oauth2 use of it This commit is the first in a series towards the goal of addressing the FIXME comment in modules/setting/oauth2.go to remove GeneralTokenSigningSecret To do it properly, the task also requires addition of signing secret/key rotation: We ultimately want to be able to change a signing key, but continue to accept the previous one. This is particularly relevant to offer a path from GeneralTokenSigningSecret aka JWT_SECRET to new, specific component key configuration, where it should be possible to add the former JWT_SECRET as a key accepted for verification to enable a seamless transition. This perspective, in turn, calls for refactoring of the existing secret initialization code to centralize the common functions of parsing signing key related configuration directives: The oauth2 module currently is the only component accepting symmetric and asymmetric keys, with the limitation of the symmetric key being also the GeneralTokenSigningSecret. Other components either enforce HS256 or public key algorithms. We should really give the choice of algorithm selection and avoid code duplication in other places, so this commit - generalizes setting parsing into a configuration struct: A prefix can be provided, with which the common configuration directives are processed: - [pfx]SIGNING_ALGORITHM determines the algorithm - [pfx]SECRET is a literal secret for symmetric algorithms - [pfx]SECRET_URI is the uri of a secret for symmetric algorithms - [pfx]SIGNING_PRIVATE_KEY_FILE is a file with a private key for asymmetric algorithms - which is then accepted by jwtx.InitSigningKey() to create an actual signing key The reasons for the two stage process are explained in a long-ish comment in modules/setting/security.go. In short, other options would either violate sensible module boundaries or cause too much friction. These other options have actually been tried, this is take 3 of the proposed changes. ### Refactor services/lfs: Change token code to use SigningKey This now also enables use of token algorithms other than HS256. In this case, signing key initialization also happens during settings initialization, because LFS is also used in CLI commands. ### Refactor api/actions to use new signingkey API This now also enables use of symmetric token algorithms. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11194 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Nils Goroll <nils.goroll@uplex.de> Co-committed-by: Nils Goroll <nils.goroll@uplex.de>
2026-04-21 19:39:33 +02:00
assert.Equal(t, "RS256", Actions.KeyCfg.Signing.Algorithm)
assert.Equal(t, "/home/app/data/actions_id_token/private.pem", *Actions.KeyCfg.Signing.PrivateKeyPath)
feat: add OIDC workload identity federation support (#10481) Add support for OIDC workload identity federation. Add ID_TOKEN_SIGNING_ALGORITHM, ID_TOKEN_SIGNING_PRIVATE_KEY_FILE, and ID_TOKEN_EXPIRATION_TIME settings to settings.actions to allow for admin configuration of this functionality. Add OIDC endpoints (/.well-known/openid-configuration and /.well-known/keys) underneath the "/api/actions" route. Add a token generation endpoint (/_apis/pipelines/workflows/{run_id}/idtoken) underneath the "/api/actions" route. Depends on: https://code.forgejo.org/forgejo/runner/pulls/1232 Docs PR: https://codeberg.org/forgejo/docs/pulls/1667 Signed-off-by: Mario Minardi <mminardi@shaw.ca> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10481 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Mario Minardi <mminardi@shaw.ca> Co-committed-by: Mario Minardi <mminardi@shaw.ca>
2026-01-15 03:39:00 +01:00
assert.EqualValues(t, 3600, Actions.IDTokenExpirationTime)
iniStr = `
[actions]
ID_TOKEN_SIGNING_ALGORITHM = ES256
ID_TOKEN_SIGNING_PRIVATE_KEY_FILE = /test/test.pem
ID_TOKEN_EXPIRATION_TIME = 120
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
chore: unify signing key configuration across modules (#11194) ## Context the three commits in this series are the first step towards the goal of removing the special casing around `JWT_SECRET`, which is used for various modules via `GetGeneralTokenSigningSecret()`. Ultimately, I want to work towards enabling seamless migration away from general use of the common secret. To enable this, we need proper secret/key rotation support, that is, we need to allow for configuration of additional secrets/keys which are accepted for token validation, but not used to issue tokens. I have this _Verifier_ support basically implemented, but this PR is not it. This PR contains cleanup refactoring which I worked on before writing the _Verifier_ support, because I noticed that the existing secret/key handling across modules was inconsistent and required duplicated code. I am submitting this part now to allow for incremental review of not too large a diff, and because these commits remained unchanged during two weeks since I moved on the the next task. ## The problem being addressed Configuration of JWT signing secrets/keys was inconsistent: Under `[oauth2]` the full configuration set was supported: - `JWT_SIGNING_ALGORITHM` configured the algorithm - `JWT_SECRET` configured a literal secret for symmetric algorithms - `JWT_SECRET_URI` configured a `file:` uri of a secret for symmetric algorithms - `JWT_SIGNING_PRIVATE_KEY_FILE` configured a file for asymmetric algorithms For `[server]`, the LFS module only supported `LFS_JWT_SECRET`, and the signing method was hardcoded to `HS256` For `[actions]`, only asymmetric signing methods were supported via `ID_TOKEN_SIGNING_ALGORITHM` and `ID_TOKEN_SIGNING_PRIVATE_KEY_FILE`. ## ini unification The proposed code centralizes ini parsing to always support the following ini keys: - `[pfx]SIGNING_ALGORITHM` determines the algorithm - `[pfx]SECRET` is a literal secret for symmetric algorithms - `[pfx]SECRET_URI` is the uri of a secret for symmetric algorithms - `[pfx]SIGNING_PRIVATE_KEY_FILE` is a file with a private key for asymmetric algorithms `[pfx]` is specific to the module and chosen to support the existing ini keys Centralizing this code and unifying the ini keys will come handy for at least the following reasons: - consistent behavior across modules is easier to understand - less duplicated code - easier to expand later, which is my main motivation ## implementation notes as might be apparent by the _take3_ branch name, this is the third iteration of this patch series. The main reason why I abandoned the other two is that I first tried to move all the key initialization into the code called from settings.go when the ini file is parsed. But that lead to a lot of friction with test cases, because private key files which are configured, but do not exist will get created and hence require a writable `AppDataPath` and additional clean up. To avoid a lot of noise and complications in test cases, I kept the existing two stage process, where - the settings component creates missing symmetric signing keys and writes them to the .ini - the settings component creates a simple configuration struct - which is then used from the module init to create the actual key, which also includes creating a private key file if asymmetric crypto is configured and the key file does not exist. I would have wished this patch was a net negative in terms of LOCs, but I hope it contributes to clarity and many added lines are in test cases. ## Commits Because sometimes PRs are merged as squashes with the PR text remaining, I am repeating here the individual messages of the individual commits for future reference: ### Refactor signing key initalization and oauth2 use of it This commit is the first in a series towards the goal of addressing the FIXME comment in modules/setting/oauth2.go to remove GeneralTokenSigningSecret To do it properly, the task also requires addition of signing secret/key rotation: We ultimately want to be able to change a signing key, but continue to accept the previous one. This is particularly relevant to offer a path from GeneralTokenSigningSecret aka JWT_SECRET to new, specific component key configuration, where it should be possible to add the former JWT_SECRET as a key accepted for verification to enable a seamless transition. This perspective, in turn, calls for refactoring of the existing secret initialization code to centralize the common functions of parsing signing key related configuration directives: The oauth2 module currently is the only component accepting symmetric and asymmetric keys, with the limitation of the symmetric key being also the GeneralTokenSigningSecret. Other components either enforce HS256 or public key algorithms. We should really give the choice of algorithm selection and avoid code duplication in other places, so this commit - generalizes setting parsing into a configuration struct: A prefix can be provided, with which the common configuration directives are processed: - [pfx]SIGNING_ALGORITHM determines the algorithm - [pfx]SECRET is a literal secret for symmetric algorithms - [pfx]SECRET_URI is the uri of a secret for symmetric algorithms - [pfx]SIGNING_PRIVATE_KEY_FILE is a file with a private key for asymmetric algorithms - which is then accepted by jwtx.InitSigningKey() to create an actual signing key The reasons for the two stage process are explained in a long-ish comment in modules/setting/security.go. In short, other options would either violate sensible module boundaries or cause too much friction. These other options have actually been tried, this is take 3 of the proposed changes. ### Refactor services/lfs: Change token code to use SigningKey This now also enables use of token algorithms other than HS256. In this case, signing key initialization also happens during settings initialization, because LFS is also used in CLI commands. ### Refactor api/actions to use new signingkey API This now also enables use of symmetric token algorithms. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11194 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Nils Goroll <nils.goroll@uplex.de> Co-committed-by: Nils Goroll <nils.goroll@uplex.de>
2026-04-21 19:39:33 +02:00
assert.Equal(t, "ES256", Actions.KeyCfg.Signing.Algorithm)
assert.Equal(t, "/test/test.pem", *Actions.KeyCfg.Signing.PrivateKeyPath)
feat: add OIDC workload identity federation support (#10481) Add support for OIDC workload identity federation. Add ID_TOKEN_SIGNING_ALGORITHM, ID_TOKEN_SIGNING_PRIVATE_KEY_FILE, and ID_TOKEN_EXPIRATION_TIME settings to settings.actions to allow for admin configuration of this functionality. Add OIDC endpoints (/.well-known/openid-configuration and /.well-known/keys) underneath the "/api/actions" route. Add a token generation endpoint (/_apis/pipelines/workflows/{run_id}/idtoken) underneath the "/api/actions" route. Depends on: https://code.forgejo.org/forgejo/runner/pulls/1232 Docs PR: https://codeberg.org/forgejo/docs/pulls/1667 Signed-off-by: Mario Minardi <mminardi@shaw.ca> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10481 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Mario Minardi <mminardi@shaw.ca> Co-committed-by: Mario Minardi <mminardi@shaw.ca>
2026-01-15 03:39:00 +01:00
assert.EqualValues(t, 120, Actions.IDTokenExpirationTime)
iniStr = `
[actions]
ID_TOKEN_SIGNING_ALGORITHM = EdDSA
ID_TOKEN_SIGNING_PRIVATE_KEY_FILE = ./test/test.pem
ID_TOKEN_EXPIRATION_TIME = 123
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
require.NoError(t, loadActionsFrom(cfg))
chore: unify signing key configuration across modules (#11194) ## Context the three commits in this series are the first step towards the goal of removing the special casing around `JWT_SECRET`, which is used for various modules via `GetGeneralTokenSigningSecret()`. Ultimately, I want to work towards enabling seamless migration away from general use of the common secret. To enable this, we need proper secret/key rotation support, that is, we need to allow for configuration of additional secrets/keys which are accepted for token validation, but not used to issue tokens. I have this _Verifier_ support basically implemented, but this PR is not it. This PR contains cleanup refactoring which I worked on before writing the _Verifier_ support, because I noticed that the existing secret/key handling across modules was inconsistent and required duplicated code. I am submitting this part now to allow for incremental review of not too large a diff, and because these commits remained unchanged during two weeks since I moved on the the next task. ## The problem being addressed Configuration of JWT signing secrets/keys was inconsistent: Under `[oauth2]` the full configuration set was supported: - `JWT_SIGNING_ALGORITHM` configured the algorithm - `JWT_SECRET` configured a literal secret for symmetric algorithms - `JWT_SECRET_URI` configured a `file:` uri of a secret for symmetric algorithms - `JWT_SIGNING_PRIVATE_KEY_FILE` configured a file for asymmetric algorithms For `[server]`, the LFS module only supported `LFS_JWT_SECRET`, and the signing method was hardcoded to `HS256` For `[actions]`, only asymmetric signing methods were supported via `ID_TOKEN_SIGNING_ALGORITHM` and `ID_TOKEN_SIGNING_PRIVATE_KEY_FILE`. ## ini unification The proposed code centralizes ini parsing to always support the following ini keys: - `[pfx]SIGNING_ALGORITHM` determines the algorithm - `[pfx]SECRET` is a literal secret for symmetric algorithms - `[pfx]SECRET_URI` is the uri of a secret for symmetric algorithms - `[pfx]SIGNING_PRIVATE_KEY_FILE` is a file with a private key for asymmetric algorithms `[pfx]` is specific to the module and chosen to support the existing ini keys Centralizing this code and unifying the ini keys will come handy for at least the following reasons: - consistent behavior across modules is easier to understand - less duplicated code - easier to expand later, which is my main motivation ## implementation notes as might be apparent by the _take3_ branch name, this is the third iteration of this patch series. The main reason why I abandoned the other two is that I first tried to move all the key initialization into the code called from settings.go when the ini file is parsed. But that lead to a lot of friction with test cases, because private key files which are configured, but do not exist will get created and hence require a writable `AppDataPath` and additional clean up. To avoid a lot of noise and complications in test cases, I kept the existing two stage process, where - the settings component creates missing symmetric signing keys and writes them to the .ini - the settings component creates a simple configuration struct - which is then used from the module init to create the actual key, which also includes creating a private key file if asymmetric crypto is configured and the key file does not exist. I would have wished this patch was a net negative in terms of LOCs, but I hope it contributes to clarity and many added lines are in test cases. ## Commits Because sometimes PRs are merged as squashes with the PR text remaining, I am repeating here the individual messages of the individual commits for future reference: ### Refactor signing key initalization and oauth2 use of it This commit is the first in a series towards the goal of addressing the FIXME comment in modules/setting/oauth2.go to remove GeneralTokenSigningSecret To do it properly, the task also requires addition of signing secret/key rotation: We ultimately want to be able to change a signing key, but continue to accept the previous one. This is particularly relevant to offer a path from GeneralTokenSigningSecret aka JWT_SECRET to new, specific component key configuration, where it should be possible to add the former JWT_SECRET as a key accepted for verification to enable a seamless transition. This perspective, in turn, calls for refactoring of the existing secret initialization code to centralize the common functions of parsing signing key related configuration directives: The oauth2 module currently is the only component accepting symmetric and asymmetric keys, with the limitation of the symmetric key being also the GeneralTokenSigningSecret. Other components either enforce HS256 or public key algorithms. We should really give the choice of algorithm selection and avoid code duplication in other places, so this commit - generalizes setting parsing into a configuration struct: A prefix can be provided, with which the common configuration directives are processed: - [pfx]SIGNING_ALGORITHM determines the algorithm - [pfx]SECRET is a literal secret for symmetric algorithms - [pfx]SECRET_URI is the uri of a secret for symmetric algorithms - [pfx]SIGNING_PRIVATE_KEY_FILE is a file with a private key for asymmetric algorithms - which is then accepted by jwtx.InitSigningKey() to create an actual signing key The reasons for the two stage process are explained in a long-ish comment in modules/setting/security.go. In short, other options would either violate sensible module boundaries or cause too much friction. These other options have actually been tried, this is take 3 of the proposed changes. ### Refactor services/lfs: Change token code to use SigningKey This now also enables use of token algorithms other than HS256. In this case, signing key initialization also happens during settings initialization, because LFS is also used in CLI commands. ### Refactor api/actions to use new signingkey API This now also enables use of symmetric token algorithms. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11194 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Nils Goroll <nils.goroll@uplex.de> Co-committed-by: Nils Goroll <nils.goroll@uplex.de>
2026-04-21 19:39:33 +02:00
assert.Equal(t, "EdDSA", Actions.KeyCfg.Signing.Algorithm)
assert.Equal(t, "/home/app/data/test/test.pem", *Actions.KeyCfg.Signing.PrivateKeyPath)
feat: add OIDC workload identity federation support (#10481) Add support for OIDC workload identity federation. Add ID_TOKEN_SIGNING_ALGORITHM, ID_TOKEN_SIGNING_PRIVATE_KEY_FILE, and ID_TOKEN_EXPIRATION_TIME settings to settings.actions to allow for admin configuration of this functionality. Add OIDC endpoints (/.well-known/openid-configuration and /.well-known/keys) underneath the "/api/actions" route. Add a token generation endpoint (/_apis/pipelines/workflows/{run_id}/idtoken) underneath the "/api/actions" route. Depends on: https://code.forgejo.org/forgejo/runner/pulls/1232 Docs PR: https://codeberg.org/forgejo/docs/pulls/1667 Signed-off-by: Mario Minardi <mminardi@shaw.ca> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10481 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Mario Minardi <mminardi@shaw.ca> Co-committed-by: Mario Minardi <mminardi@shaw.ca>
2026-01-15 03:39:00 +01:00
assert.EqualValues(t, 123, Actions.IDTokenExpirationTime)
iniStr = `
[actions]
ID_TOKEN_SIGNING_ALGORITHM = HS256
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
err = loadActionsFrom(cfg)
chore: unify signing key configuration across modules (#11194) ## Context the three commits in this series are the first step towards the goal of removing the special casing around `JWT_SECRET`, which is used for various modules via `GetGeneralTokenSigningSecret()`. Ultimately, I want to work towards enabling seamless migration away from general use of the common secret. To enable this, we need proper secret/key rotation support, that is, we need to allow for configuration of additional secrets/keys which are accepted for token validation, but not used to issue tokens. I have this _Verifier_ support basically implemented, but this PR is not it. This PR contains cleanup refactoring which I worked on before writing the _Verifier_ support, because I noticed that the existing secret/key handling across modules was inconsistent and required duplicated code. I am submitting this part now to allow for incremental review of not too large a diff, and because these commits remained unchanged during two weeks since I moved on the the next task. ## The problem being addressed Configuration of JWT signing secrets/keys was inconsistent: Under `[oauth2]` the full configuration set was supported: - `JWT_SIGNING_ALGORITHM` configured the algorithm - `JWT_SECRET` configured a literal secret for symmetric algorithms - `JWT_SECRET_URI` configured a `file:` uri of a secret for symmetric algorithms - `JWT_SIGNING_PRIVATE_KEY_FILE` configured a file for asymmetric algorithms For `[server]`, the LFS module only supported `LFS_JWT_SECRET`, and the signing method was hardcoded to `HS256` For `[actions]`, only asymmetric signing methods were supported via `ID_TOKEN_SIGNING_ALGORITHM` and `ID_TOKEN_SIGNING_PRIVATE_KEY_FILE`. ## ini unification The proposed code centralizes ini parsing to always support the following ini keys: - `[pfx]SIGNING_ALGORITHM` determines the algorithm - `[pfx]SECRET` is a literal secret for symmetric algorithms - `[pfx]SECRET_URI` is the uri of a secret for symmetric algorithms - `[pfx]SIGNING_PRIVATE_KEY_FILE` is a file with a private key for asymmetric algorithms `[pfx]` is specific to the module and chosen to support the existing ini keys Centralizing this code and unifying the ini keys will come handy for at least the following reasons: - consistent behavior across modules is easier to understand - less duplicated code - easier to expand later, which is my main motivation ## implementation notes as might be apparent by the _take3_ branch name, this is the third iteration of this patch series. The main reason why I abandoned the other two is that I first tried to move all the key initialization into the code called from settings.go when the ini file is parsed. But that lead to a lot of friction with test cases, because private key files which are configured, but do not exist will get created and hence require a writable `AppDataPath` and additional clean up. To avoid a lot of noise and complications in test cases, I kept the existing two stage process, where - the settings component creates missing symmetric signing keys and writes them to the .ini - the settings component creates a simple configuration struct - which is then used from the module init to create the actual key, which also includes creating a private key file if asymmetric crypto is configured and the key file does not exist. I would have wished this patch was a net negative in terms of LOCs, but I hope it contributes to clarity and many added lines are in test cases. ## Commits Because sometimes PRs are merged as squashes with the PR text remaining, I am repeating here the individual messages of the individual commits for future reference: ### Refactor signing key initalization and oauth2 use of it This commit is the first in a series towards the goal of addressing the FIXME comment in modules/setting/oauth2.go to remove GeneralTokenSigningSecret To do it properly, the task also requires addition of signing secret/key rotation: We ultimately want to be able to change a signing key, but continue to accept the previous one. This is particularly relevant to offer a path from GeneralTokenSigningSecret aka JWT_SECRET to new, specific component key configuration, where it should be possible to add the former JWT_SECRET as a key accepted for verification to enable a seamless transition. This perspective, in turn, calls for refactoring of the existing secret initialization code to centralize the common functions of parsing signing key related configuration directives: The oauth2 module currently is the only component accepting symmetric and asymmetric keys, with the limitation of the symmetric key being also the GeneralTokenSigningSecret. Other components either enforce HS256 or public key algorithms. We should really give the choice of algorithm selection and avoid code duplication in other places, so this commit - generalizes setting parsing into a configuration struct: A prefix can be provided, with which the common configuration directives are processed: - [pfx]SIGNING_ALGORITHM determines the algorithm - [pfx]SECRET is a literal secret for symmetric algorithms - [pfx]SECRET_URI is the uri of a secret for symmetric algorithms - [pfx]SIGNING_PRIVATE_KEY_FILE is a file with a private key for asymmetric algorithms - which is then accepted by jwtx.InitSigningKey() to create an actual signing key The reasons for the two stage process are explained in a long-ish comment in modules/setting/security.go. In short, other options would either violate sensible module boundaries or cause too much friction. These other options have actually been tried, this is take 3 of the proposed changes. ### Refactor services/lfs: Change token code to use SigningKey This now also enables use of token algorithms other than HS256. In this case, signing key initialization also happens during settings initialization, because LFS is also used in CLI commands. ### Refactor api/actions to use new signingkey API This now also enables use of symmetric token algorithms. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11194 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Nils Goroll <nils.goroll@uplex.de> Co-committed-by: Nils Goroll <nils.goroll@uplex.de>
2026-04-21 19:39:33 +02:00
require.ErrorContains(t, err, "[actions] Unexpected algorithm: ID_TOKEN_SIGNING_ALGORITHM = HS256, needs to be one of [RS256 RS384 RS512 ES256 ES384 ES512 EdDSA]")
iniStr = `
[actions]
ID_TOKEN_SECRET = ABC
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
err = loadActionsFrom(cfg)
require.ErrorContains(t, err, "[actions] Invalid config key: ID_TOKEN_SECRET - must be removed")
iniStr = `
[actions]
ID_TOKEN_SECRET_URI = ABC
`
cfg, err = NewConfigProviderFromData(iniStr)
require.NoError(t, err)
err = loadActionsFrom(cfg)
require.ErrorContains(t, err, "[actions] Invalid config key: ID_TOKEN_SECRET_URI - must be removed")
feat: add OIDC workload identity federation support (#10481) Add support for OIDC workload identity federation. Add ID_TOKEN_SIGNING_ALGORITHM, ID_TOKEN_SIGNING_PRIVATE_KEY_FILE, and ID_TOKEN_EXPIRATION_TIME settings to settings.actions to allow for admin configuration of this functionality. Add OIDC endpoints (/.well-known/openid-configuration and /.well-known/keys) underneath the "/api/actions" route. Add a token generation endpoint (/_apis/pipelines/workflows/{run_id}/idtoken) underneath the "/api/actions" route. Depends on: https://code.forgejo.org/forgejo/runner/pulls/1232 Docs PR: https://codeberg.org/forgejo/docs/pulls/1667 Signed-off-by: Mario Minardi <mminardi@shaw.ca> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10481 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Mario Minardi <mminardi@shaw.ca> Co-committed-by: Mario Minardi <mminardi@shaw.ca>
2026-01-15 03:39:00 +01:00
}