-
Notifications
You must be signed in to change notification settings - Fork 58
feat: add $HOSTNAME substitution in privilege policy #1360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kevinl03
wants to merge
4
commits into
ubuntu:main
Choose a base branch
from
kevinl03:fix-hostname-substitution-1037
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
89d6fe9
feat: add $HOSTNAME substitution in privilege policy
kevinl03 ed0e6b2
test: add golden file for HOSTNAME substitution test
kevinl03 fa0864d
feat: add $HOSTNAME substitution in privilege policy
kevinl03 68813ea
refactor: replace hostname in test files instead of using TestHostnam…
kevinl03 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| "context" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
|
|
@@ -34,10 +35,13 @@ | |
| "Allow local admins with no other rules is a noop": {entries: []entry.Entry{{Key: "allow-local-admins", Disabled: false}}}, | ||
|
|
||
| // client admins from AD | ||
| "Set client user admins": {entries: []entry.Entry{{Key: "client-admins", Value: "alice@domain.com"}}}, | ||
| "Set client multiple users admins": {entries: []entry.Entry{{Key: "client-admins", Value: "alice@domain.com,domain\\bob,carole cosmic@otherdomain.com"}}}, | ||
| "Set client group admins": {entries: []entry.Entry{{Key: "client-admins", Value: "%group@domain.com"}}}, | ||
| "Set client mixed with users and group admins": {entries: []entry.Entry{{Key: "client-admins", Value: "alice@domain.com,%group@domain.com"}}}, | ||
| "Set client admins with HOSTNAME substitution": {entries: []entry.Entry{{Key: "client-admins", Value: "secLocalAdmin-$HOSTNAME@domain.com"}}}, | ||
| "Set client admins with multiple HOSTNAME substitutions": {entries: []entry.Entry{{Key: "client-admins", Value: "x-$HOSTNAME-y-$HOSTNAME@domain.com"}}}, | ||
| "Set client group admins with HOSTNAME substitution": {entries: []entry.Entry{{Key: "client-admins", Value: "%admins-$HOSTNAME@domain.com"}}}, | ||
| "Empty client AD admins": {entries: []entry.Entry{{Key: "client-admins", Value: ""}}}, | ||
| "No client AD admins": {entries: []entry.Entry{{Key: "client-admins", Disabled: true}}}, | ||
|
|
||
|
|
@@ -131,7 +135,75 @@ | |
| } | ||
| require.NoError(t, err, "ApplyPolicy failed but shouldn't have") | ||
|
|
||
| // Replace hostname in generated files for tests using $HOSTNAME substitution | ||
| // This ensures golden files are machine-independent | ||
| needsReplacement := false | ||
| for _, entry := range tc.entries { | ||
| if entry.Key == "client-admins" && strings.Contains(entry.Value, "$HOSTNAME") { | ||
| needsReplacement = true | ||
| break | ||
| } | ||
| } | ||
| if needsReplacement { | ||
| replaceHostnameInGeneratedFiles(t, tmpRootDir, "testhost") | ||
| } | ||
|
|
||
| testutils.CompareTreesWithFiltering(t, filepath.Join(tmpRootDir, "etc"), testutils.GoldenPath(t), testutils.UpdateEnabled()) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| // replaceHostnameInGeneratedFiles replaces the actual hostname with a generic one in generated files | ||
| // to ensure golden files are machine-independent. | ||
| func replaceHostnameInGeneratedFiles(t *testing.T, rootDir, replacement string) { | ||
| t.Helper() | ||
|
|
||
| // Get the actual hostname | ||
| hostname, err := os.Hostname() | ||
| require.NoError(t, err, "Setup: Failed to get hostname") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are at the end of the tests here, so the messages should be "Teardown: ..." rather than "Setup: ..." |
||
| if hostname == replacement { | ||
| // Already using the replacement, no need to replace | ||
| return | ||
| } | ||
|
|
||
| // Files that might contain the hostname | ||
| files := []string{ | ||
| filepath.Join(rootDir, "etc", "sudoers.d", "99-adsys-privilege-enforcement"), | ||
| filepath.Join(rootDir, "etc", "polkit-1", "rules.d", "00-adsys-privilege-enforcement.rules"), | ||
| filepath.Join(rootDir, "etc", "polkit-1", "localauthority.conf.d", "99-adsys-privilege-enforcement.conf"), | ||
| } | ||
|
|
||
| for _, file := range files { | ||
| // Check if file exists | ||
| if _, err := os.Stat(file); os.IsNotExist(err) { | ||
| continue | ||
| } | ||
|
|
||
| // Read file content | ||
| content, err := os.ReadFile(file) | ||
| require.NoError(t, err, "Setup: Failed to read file %s", file) | ||
|
|
||
| // Replace hostname with generic one | ||
| newContent := strings.ReplaceAll(string(content), hostname, replacement) | ||
|
|
||
| // Write back if changed | ||
| if string(content) != newContent { | ||
| // Get original file permissions | ||
| info, err := os.Stat(file) | ||
| require.NoError(t, err, "Setup: Failed to stat file %s", file) | ||
| originalMode := info.Mode() | ||
|
|
||
| // Make file writable temporarily | ||
| err = os.Chmod(file, 0644) | ||
| require.NoError(t, err, "Setup: Failed to make file writable %s", file) | ||
|
|
||
| // Write the modified content | ||
| err = os.WriteFile(file, []byte(newContent), originalMode) | ||
| require.NoError(t, err, "Setup: Failed to write file %s", file) | ||
|
|
||
| // Restore original permissions | ||
| err = os.Chmod(file, originalMode) | ||
| require.NoError(t, err, "Setup: Failed to restore file permissions %s", file) | ||
| } | ||
| } | ||
| } | ||
7 changes: 7 additions & 0 deletions
7
...t_admins_with_hostname_substitution/polkit-1/rules.d/00-adsys-privilege-enforcement.rules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // This file is managed by adsys. | ||
| // Do not edit this file manually. | ||
| // Any changes will be overwritten. | ||
|
|
||
| polkit.addAdminRule(function(action, subject){ | ||
| return ["unix-user:secLocalAdmin-testhost@domain.com"]; | ||
| }); |
6 changes: 6 additions & 0 deletions
6
...den/set_client_admins_with_hostname_substitution/sudoers.d/99-adsys-privilege-enforcement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # This file is managed by adsys. | ||
| # Do not edit this file manually. | ||
| # Any changes will be overwritten. | ||
|
|
||
| "secLocalAdmin-testhost@domain.com" ALL=(ALL:ALL) ALL | ||
|
|
7 changes: 7 additions & 0 deletions
7
...ith_multiple_hostname_substitutions/polkit-1/rules.d/00-adsys-privilege-enforcement.rules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // This file is managed by adsys. | ||
| // Do not edit this file manually. | ||
| // Any changes will be overwritten. | ||
|
|
||
| polkit.addAdminRule(function(action, subject){ | ||
| return ["unix-user:x-testhost-y-testhost@domain.com"]; | ||
| }); |
6 changes: 6 additions & 0 deletions
6
...ient_admins_with_multiple_hostname_substitutions/sudoers.d/99-adsys-privilege-enforcement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # This file is managed by adsys. | ||
| # Do not edit this file manually. | ||
| # Any changes will be overwritten. | ||
|
|
||
| "x-testhost-y-testhost@domain.com" ALL=(ALL:ALL) ALL | ||
|
|
7 changes: 7 additions & 0 deletions
7
...p_admins_with_hostname_substitution/polkit-1/rules.d/00-adsys-privilege-enforcement.rules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // This file is managed by adsys. | ||
| // Do not edit this file manually. | ||
| // Any changes will be overwritten. | ||
|
|
||
| polkit.addAdminRule(function(action, subject){ | ||
| return ["unix-group:admins-testhost@domain.com"]; | ||
| }); |
6 changes: 6 additions & 0 deletions
6
...t_client_group_admins_with_hostname_substitution/sudoers.d/99-adsys-privilege-enforcement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # This file is managed by adsys. | ||
| # Do not edit this file manually. | ||
| # Any changes will be overwritten. | ||
|
|
||
| "%admins-testhost@domain.com" ALL=(ALL:ALL) ALL | ||
|
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I can see the reasoning behind this logic, it's probably unnecessary. Looping through the entries to determine whether we need hostname replacement or not is more costly than just storing the hostname from the get go, so we should just do something like:
Makes the code simpler and easier to quickly scan through it