fix: fix permission on windows

This commit is contained in:
fengcaiwen
2023-01-25 13:16:51 +08:00
parent 17bc64559b
commit b387a1d55e
12 changed files with 646 additions and 102 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -13,7 +13,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.19
check-latest: true
cache: true
- name: Checkout code

View File

@@ -14,7 +14,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.19
check-latest: true
cache: true
- name: Push image to docker hub
@@ -31,7 +31,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.19
check-latest: true
cache: true
- name: Setup Minikube
@@ -74,7 +74,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.19
check-latest: true
cache: true
- uses: docker-practice/actions-setup-docker@master
@@ -130,7 +130,7 @@ jobs:
# - name: Set up Go
# uses: actions/setup-go@v2
# with:
# go-version: 1.18
# go-version: 1.19
# # - run: |
# # choco install docker-desktop
# # docker version

View File

@@ -24,7 +24,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.19
check-latest: true
cache: true
- name: Checkout code

View File

@@ -1,7 +1,7 @@
ARG BASE=github.com/wencaiwulue/kubevpn
FROM envoyproxy/envoy:v1.21.1 AS envoy
FROM golang:1.18 AS builder
FROM golang:1.19 AS builder
COPY . /go/src/$BASE

View File

@@ -70,7 +70,15 @@ func updateRefCount(configMapInterface v12.ConfigMapInterface, name string, incr
err = retry.OnError(
retry.DefaultRetry,
func(err error) bool {
return !k8serrors.IsNotFound(err)
notFound := k8serrors.IsNotFound(err)
if notFound {
return false
}
conflict := k8serrors.IsConflict(err)
if conflict {
return true
}
return false
},
func() (err error) {
var cm *corev1.ConfigMap

View File

@@ -4,34 +4,86 @@
package util
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/pkg/util/wintoken"
"os"
"strings"
"os/exec"
"os/signal"
"syscall"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
// ref https://stackoverflow.com/questions/31558066/how-to-ask-for-administer-privileges-on-windows-with-go
// ref https://stackoverflow.com/questions/31558066/how-to-ask-for-administer-privileges-on-windows-with-go
func RunWithElevated() {
verb := "runas"
exe, _ := os.Executable()
cwd, _ := os.Getwd()
args := strings.Join(os.Args[1:], " ")
verbPtr, _ := windows.UTF16PtrFromString(verb)
exePtr, _ := syscall.UTF16PtrFromString(exe)
cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
argPtr, _ := syscall.UTF16PtrFromString(args)
var showCmd int32 = 1 //SW_NORMAL
err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd)
cmd := exec.Command(exe, "connect")
log.Debug(cmd.Args)
fmt.Println(cmd.Args)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Env = append(os.Environ(), "KUBECONFIG="+os.Getenv("KUBECONFIG"))
//token, err := wintoken.GetInteractiveToken(wintoken.TokenLinked)
//if err != nil {
// panic(err)
//}
token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary)
if err != nil {
logrus.Warn(err)
panic(err)
}
err = token.EnableAllPrivileges()
if err != nil {
panic(err)
}
defer token.Close()
cmd.SysProcAttr = &syscall.SysProcAttr{
Token: syscall.Token(token.Token()),
}
// while send single CTRL+C, command will quit immediately, but output will cut off and print util quit final
// so, mute single CTRL+C, let inner command handle single only
go func() {
signals := make(chan os.Signal)
signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL)
<-signals
}()
err = cmd.Run()
if err != nil {
log.Warn(err)
}
}
//func RunWithElevated() {
// verb := "runas"
// //exe, _ := os.Executable()
// cwd, _ := os.Getwd()
// args := strings.Join(os.Args[:], " ")
//
// //verbPtr, _ := windows.UTF16PtrFromString(verb)
// //exePtr, _ := syscall.UTF16PtrFromString(exe)
// cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
// argPtr, _ := syscall.UTF16PtrFromString(args)
//
// // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
// //var showCmd int32 = 1 //SW_NORMAL
// //process := windows.CurrentProcess()
// //process := windows.GetDesktopWindow()
// //windows.Setenv("KUBECONFIG", os.Getenv("KUBECONFIG"))
// v, _ := syscall.UTF16PtrFromString("KUBECONFIG=" + os.Getenv("KUBECONFIG"))
//
// var si windows.StartupInfo
// var pi windows.ProcessInformation
////windows.TokenElevation
// // CreateProcess(NULL,"cleanmgr",NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi); //调用系统的清理磁盘程序
// err := windows.CreateProcessAsUser(nil,nil, argPtr, nil, nil, true, windows.NORMAL_PRIORITY_CLASS, v, cwdPtr, &si, &pi)
// //r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd))
// //r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0)
// //err := windows.ShellExecute(windows.Handle(process), verbPtr, exePtr, argPtr, cwdPtr, showCmd)
// if err != nil {
// logrus.Warn(err)
// }
//}
func IsAdmin() bool {
_, err := os.Open("\\\\.\\PHYSICALDRIVE0")
if err != nil {

View File

@@ -0,0 +1,139 @@
//go:build windows
// +build windows
package wintoken
import (
"fmt"
"unsafe"
"golang.org/x/sys/windows"
)
const (
WTS_CURRENT_SERVER_HANDLE windows.Handle = 0
)
// OpenProcessToken opens a process token using PID, pass 0 as PID for self token
func OpenProcessToken(pid int, tokenType tokenType) (*Token, error) {
var (
t windows.Token
duplicatedToken windows.Token
procHandle windows.Handle
err error
)
if pid == 0 {
procHandle = windows.CurrentProcess()
} else {
procHandle, err = windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid))
}
if err != nil {
return nil, err
}
if err = windows.OpenProcessToken(procHandle, windows.TOKEN_ALL_ACCESS, &t); err != nil {
return nil, err
}
defer windows.CloseHandle(windows.Handle(t))
switch tokenType {
case TokenPrimary:
if err := windows.DuplicateTokenEx(t, windows.MAXIMUM_ALLOWED, nil, windows.SecurityDelegation, windows.TokenPrimary, &duplicatedToken); err != nil {
return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err)
}
case TokenImpersonation:
if err := windows.DuplicateTokenEx(t, windows.MAXIMUM_ALLOWED, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken); err != nil {
return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err)
}
case TokenLinked:
if err := windows.DuplicateTokenEx(t, windows.MAXIMUM_ALLOWED, nil, windows.SecurityDelegation, windows.TokenPrimary, &duplicatedToken); err != nil {
return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err)
}
dt, err := duplicatedToken.GetLinkedToken()
windows.CloseHandle(windows.Handle(duplicatedToken))
if err != nil {
return nil, fmt.Errorf("error while getting LinkedToken: %w", err)
}
duplicatedToken = dt
}
return &Token{token: duplicatedToken, typ: tokenType}, nil
}
// GetInteractiveToken gets the interactive token associated with current logged in user
// It uses windows API WTSEnumerateSessions, WTSQueryUserToken and DuplicateTokenEx to return a valid wintoken
func GetInteractiveToken(tokenType tokenType) (*Token, error) {
switch tokenType {
case TokenPrimary, TokenImpersonation, TokenLinked:
default:
return nil, ErrOnlyPrimaryImpersonationTokenAllowed
}
var (
sessionPointer uintptr
sessionCount uint32
interactiveToken windows.Token
duplicatedToken windows.Token
sessionID uint32
)
err := windows.WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, (**windows.WTS_SESSION_INFO)(unsafe.Pointer(&sessionPointer)), &sessionCount)
if err != nil {
return nil, fmt.Errorf("error while enumerating sessions: %v", err)
}
defer windows.WTSFreeMemory(sessionPointer)
sessions := make([]*windows.WTS_SESSION_INFO, sessionCount)
size := unsafe.Sizeof(windows.WTS_SESSION_INFO{})
for i := range sessions {
sessions[i] = (*windows.WTS_SESSION_INFO)(unsafe.Pointer(sessionPointer + (size * uintptr(i))))
}
for i := range sessions {
if sessions[i].State == windows.WTSActive {
sessionID = sessions[i].SessionID
break
}
}
if sessionID == 0 {
return nil, ErrNoActiveSession
}
if err := windows.WTSQueryUserToken(sessionID, &interactiveToken); err != nil {
return nil, fmt.Errorf("error while WTSQueryUserToken: %w", err)
}
defer windows.CloseHandle(windows.Handle(interactiveToken))
switch tokenType {
case TokenPrimary:
if err := windows.DuplicateTokenEx(interactiveToken, windows.MAXIMUM_ALLOWED, nil, windows.SecurityDelegation, windows.TokenPrimary, &duplicatedToken); err != nil {
return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err)
}
case TokenImpersonation:
if err := windows.DuplicateTokenEx(interactiveToken, windows.MAXIMUM_ALLOWED, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken); err != nil {
return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err)
}
case TokenLinked:
if err := windows.DuplicateTokenEx(interactiveToken, windows.MAXIMUM_ALLOWED, nil, windows.SecurityDelegation, windows.TokenPrimary, &duplicatedToken); err != nil {
return nil, fmt.Errorf("error while DuplicateTokenEx: %w", err)
}
dt, err := duplicatedToken.GetLinkedToken()
windows.CloseHandle(windows.Handle(duplicatedToken))
if err != nil {
return nil, fmt.Errorf("error while getting LinkedToken: %w", err)
}
duplicatedToken = dt
}
if windows.Handle(duplicatedToken) == windows.InvalidHandle {
return nil, ErrInvalidDuplicatedToken
}
return &Token{typ: tokenType, token: duplicatedToken}, nil
}

11
pkg/util/wintoken/vars.go Normal file
View File

@@ -0,0 +1,11 @@
package wintoken
import "fmt"
var (
ErrNoActiveSession error = fmt.Errorf("no active session found")
ErrInvalidDuplicatedToken error = fmt.Errorf("invalid duplicated token")
ErrOnlyPrimaryImpersonationTokenAllowed error = fmt.Errorf("only primary or impersonation token types allowed")
ErrNoPrivilegesSpecified error = fmt.Errorf("no privileges specified")
ErrTokenClosed error = fmt.Errorf("token has been closed")
)

View File

@@ -0,0 +1,410 @@
//go:build windows
// +build windows
package wintoken
import (
"bytes"
"encoding/binary"
"fmt"
"unsafe"
"golang.org/x/sys/windows"
)
var (
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
procLookupPrivilegeName = modadvapi32.NewProc("LookupPrivilegeNameW")
procLookupPrivilegeDisplayName = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
)
type (
tokenType int
privModType int
)
const (
PrivDisable privModType = iota
PrivEnable
PrivRemove
)
type Token struct {
typ tokenType
token windows.Token
}
// TokenUserDetail is the structure that exposes token details
// Details contain Username, Domain, Account Type, User Profile Directory, Environment
type TokenUserDetail struct {
Username string
Domain string
AccountType uint32
UserProfileDir string
Environ []string
}
func (t TokenUserDetail) String() string {
return fmt.Sprintf("Username: %s, Domain: %s, Account Type: %d, UserProfileDir: %s", t.Username, t.Domain, t.AccountType, t.UserProfileDir)
}
// Privilege is the structure which exposes privilege details
// Details contain Name, Description, Enabled, EnabledByDefault, Removed, UsedForAccess
type Privilege struct {
Name string
Description string
Enabled bool
EnabledByDefault bool
Removed bool
UsedForAccess bool
}
func (p Privilege) String() string {
status := "Disabled"
if p.Removed {
status = "Removed"
} else if p.Enabled {
status = "Enabled"
}
return fmt.Sprintf("%s: %s", p.Name, status)
}
const (
tokenUnknown tokenType = iota
TokenPrimary
TokenImpersonation
TokenLinked
)
// NewToken can be used to supply your own token for the wintoken struct
// so you can use the same flexiblity provided by the package
func NewToken(token windows.Token, typ tokenType) *Token {
return &Token{
token: token,
typ: typ,
}
}
// Token returns the underlying token for use
func (t *Token) Token() windows.Token {
return t.token
}
// Close closes the underlying token
func (t *Token) Close() {
windows.Close(windows.Handle(t.token))
t.token = 0
}
func (t *Token) errIfTokenClosed() error {
if t.token == 0 {
return ErrTokenClosed
}
return nil
}
func lookupPrivilegeNameByLUID(luid uint64) (string, string, error) {
nameBuffer := make([]uint16, 256)
nameBufferSize := uint32(len(nameBuffer))
displayNameBuffer := make([]uint16, 256)
displayNameBufferSize := uint32(len(displayNameBuffer))
sysName, err := windows.UTF16PtrFromString("")
if err != nil {
return "", "", err
}
if r1, _, err := procLookupPrivilegeName.Call(uintptr(unsafe.Pointer(sysName)), uintptr(unsafe.Pointer(&luid)), uintptr(unsafe.Pointer(&nameBuffer[0])), uintptr(unsafe.Pointer(&nameBufferSize))); r1 == 0 {
return "", "", err
}
var langID uint32
if r1, _, err := procLookupPrivilegeDisplayName.Call(uintptr(unsafe.Pointer(sysName)), uintptr(unsafe.Pointer(&nameBuffer[0])), uintptr(unsafe.Pointer(&displayNameBuffer[0])), uintptr(unsafe.Pointer(&displayNameBufferSize)), uintptr(unsafe.Pointer(&langID))); r1 == 0 {
return "", "", err
}
return windows.UTF16ToString(nameBuffer), windows.UTF16ToString(displayNameBuffer), nil
}
// UserDetails gets User details associated with token
func (t *Token) UserDetails() (TokenUserDetail, error) {
uSid, err := t.token.GetTokenUser()
if err != nil {
return TokenUserDetail{}, err
}
user, domain, typ, err := uSid.User.Sid.LookupAccount("")
if err != nil {
return TokenUserDetail{}, err
}
uProfDir, err := t.token.GetUserProfileDirectory()
if err != nil {
return TokenUserDetail{}, err
}
env, err := t.token.Environ(false)
if err != nil {
return TokenUserDetail{}, err
}
return TokenUserDetail{Username: user, Domain: domain, AccountType: typ, UserProfileDir: uProfDir, Environ: env}, nil
}
// GetPrivileges lists all Privileges from the token
func (t *Token) GetPrivileges() ([]Privilege, error) {
if err := t.errIfTokenClosed(); err != nil {
return nil, err
}
n := uint32(0)
windows.GetTokenInformation(t.token, windows.TokenPrivileges, nil, 0, &n)
b := make([]byte, n)
if err := windows.GetTokenInformation(t.token, windows.TokenPrivileges, &b[0], uint32(len(b)), &n); err != nil {
return nil, err
}
privBuff := bytes.NewBuffer(b)
var nPrivs uint32
if err := binary.Read(privBuff, binary.LittleEndian, &nPrivs); err != nil {
return nil, fmt.Errorf("cannot read number of privileges: %w", err)
}
privDetails := make([]Privilege, int(nPrivs))
for i := 0; i < int(nPrivs); i++ {
var (
luid uint64
attributes uint32
currentPrivInfo Privilege
err error
)
if err := binary.Read(privBuff, binary.LittleEndian, &luid); err != nil {
return nil, fmt.Errorf("cannot read LUID from buffer: %w", err)
}
if err := binary.Read(privBuff, binary.LittleEndian, &attributes); err != nil {
return nil, fmt.Errorf("cannot read attributes from buffer: %w", err)
}
currentPrivInfo.Name, currentPrivInfo.Description, err = lookupPrivilegeNameByLUID(luid)
if err != nil {
return nil, fmt.Errorf("cannot get privilege info based on the LUID: %w", err)
}
currentPrivInfo.EnabledByDefault = (attributes & windows.SE_PRIVILEGE_ENABLED_BY_DEFAULT) > 0
currentPrivInfo.UsedForAccess = (attributes & windows.SE_PRIVILEGE_USED_FOR_ACCESS) > 0
currentPrivInfo.Enabled = (attributes & windows.SE_PRIVILEGE_ENABLED) > 0
currentPrivInfo.Removed = (attributes & windows.SE_PRIVILEGE_REMOVED) > 0
privDetails[i] = currentPrivInfo
}
return privDetails, nil
}
// EnableAllPrivileges enables all privileges in the token
func (t *Token) EnableAllPrivileges() error {
if err := t.errIfTokenClosed(); err != nil {
return err
}
privs, err := t.GetPrivileges()
if err != nil {
return err
}
var toBeEnabled []string
for _, p := range privs {
if !p.Removed && !p.Enabled {
toBeEnabled = append(toBeEnabled, p.Name)
}
}
return t.modifyTokenPrivileges(toBeEnabled, PrivEnable)
}
// DisableAllPrivileges disables all privileges in the token
func (t *Token) DisableAllPrivileges() error {
if err := t.errIfTokenClosed(); err != nil {
return err
}
privs, err := t.GetPrivileges()
if err != nil {
return err
}
var toBeDisabled []string
for _, p := range privs {
if !p.Removed && p.Enabled {
toBeDisabled = append(toBeDisabled, p.Name)
}
}
return t.modifyTokenPrivileges(toBeDisabled, PrivDisable)
}
// RemoveAllPrivileges removes all privileges from the token
func (t *Token) RemoveAllPrivileges() error {
if err := t.errIfTokenClosed(); err != nil {
return err
}
privs, err := t.GetPrivileges()
if err != nil {
return err
}
var toBeRemoved []string
for _, p := range privs {
if !p.Removed {
toBeRemoved = append(toBeRemoved, p.Name)
}
}
return t.modifyTokenPrivileges(toBeRemoved, PrivRemove)
}
// EnableTokenPrivileges enables token privileges by list of privilege names
func (t *Token) EnableTokenPrivileges(privs []string) error {
return t.modifyTokenPrivileges(privs, PrivEnable)
}
// DisableTokenPrivileges disables token privileges by list of privilege names
func (t *Token) DisableTokenPrivileges(privs []string) error {
return t.modifyTokenPrivileges(privs, PrivDisable)
}
// RemoveTokenPrivileges removes token privileges by list of privilege names
func (t *Token) RemoveTokenPrivileges(privs []string) error {
return t.modifyTokenPrivileges(privs, PrivRemove)
}
// EnableTokenPrivileges enables token privileges by privilege name
func (t *Token) EnableTokenPrivilege(priv string) error {
return t.modifyTokenPrivilege(priv, PrivEnable)
}
// DisableTokenPrivilege disables token privileges by privilege name
func (t *Token) DisableTokenPrivilege(priv string) error {
return t.modifyTokenPrivilege(priv, PrivDisable)
}
// RemoveTokenPrivilege removes token privileges by privilege name
func (t *Token) RemoveTokenPrivilege(priv string) error {
return t.modifyTokenPrivilege(priv, PrivRemove)
}
func (t *Token) modifyTokenPrivileges(privs []string, mode privModType) error {
if err := t.errIfTokenClosed(); err != nil {
return err
}
if len(privs) == 0 {
return ErrNoPrivilegesSpecified
}
errMsgConst := ""
switch mode {
case PrivDisable:
errMsgConst = "disabling"
case PrivEnable:
errMsgConst = "enabling"
case PrivRemove:
errMsgConst = "removing"
}
var errMsg string
for _, p := range privs {
err := t.modifyTokenPrivilege(p, mode)
if err != nil {
if len(errMsg) != 0 {
errMsg += "\n"
}
errMsg += fmt.Sprintf("%s privilege for %s failed: %s", errMsgConst, p, err)
}
}
if len(errMsg) != 0 {
return fmt.Errorf(errMsg)
}
return nil
}
func (t *Token) modifyTokenPrivilege(priv string, mode privModType) error {
if err := t.errIfTokenClosed(); err != nil {
return err
}
var luid windows.LUID
if err := windows.LookupPrivilegeValue(nil, windows.StringToUTF16Ptr(priv), &luid); err != nil {
return fmt.Errorf("LookupPrivilegeValueW failed: %w", err)
}
ap := windows.Tokenprivileges{
PrivilegeCount: 1,
}
ap.Privileges[0].Luid = luid
switch mode {
case PrivEnable:
ap.Privileges[0].Attributes = windows.SE_PRIVILEGE_ENABLED
case PrivRemove:
ap.Privileges[0].Attributes = windows.SE_PRIVILEGE_REMOVED
}
if err := windows.AdjustTokenPrivileges(t.token, false, &ap, 0, nil, nil); err != nil {
return fmt.Errorf("AdjustTokenPrivileges failed: %w", err)
}
return nil
}
// GetIntegrityLevel is used to get integrity level of the token
func (t *Token) GetIntegrityLevel() (string, error) {
if err := t.errIfTokenClosed(); err != nil {
return "", err
}
n := uint32(0)
windows.GetTokenInformation(t.token, windows.TokenIntegrityLevel, nil, 0, &n)
b := make([]byte, n)
if err := windows.GetTokenInformation(t.token, windows.TokenIntegrityLevel, &b[0], uint32(len(b)), &n); err != nil {
return "", err
}
tml := (*windows.Tokenmandatorylabel)(unsafe.Pointer(&b[0]))
sid := (*windows.SID)(unsafe.Pointer(tml.Label.Sid))
switch sid.String() {
case "S-1-16-4096":
return "Low", nil
case "S-1-16-8192":
return "Medium", nil
case "S-1-16-12288":
return "High", nil
case "S-1-16-16384":
return "System", nil
default:
return "Unknown", nil
}
}
// GetLinkedToken is used to get the linked token if any
func (t *Token) GetLinkedToken() (*Token, error) {
lt, err := t.token.GetLinkedToken()
if err != nil {
return nil, err
}
return &Token{
typ: TokenLinked,
token: lt,
}, nil
}

View File

@@ -26,43 +26,6 @@ func convertAdmissionRequestToV1(r *v1beta1.AdmissionRequest) *v1.AdmissionReque
}
}
func convertAdmissionRequestToV1beta1(r *v1.AdmissionRequest) *v1beta1.AdmissionRequest {
return &v1beta1.AdmissionRequest{
Kind: r.Kind,
Namespace: r.Namespace,
Name: r.Name,
Object: r.Object,
Resource: r.Resource,
Operation: v1beta1.Operation(r.Operation),
UID: r.UID,
DryRun: r.DryRun,
OldObject: r.OldObject,
Options: r.Options,
RequestKind: r.RequestKind,
RequestResource: r.RequestResource,
RequestSubResource: r.RequestSubResource,
SubResource: r.SubResource,
UserInfo: r.UserInfo,
}
}
func convertAdmissionResponseToV1(r *v1beta1.AdmissionResponse) *v1.AdmissionResponse {
var pt *v1.PatchType
if r.PatchType != nil {
t := v1.PatchType(*r.PatchType)
pt = &t
}
return &v1.AdmissionResponse{
UID: r.UID,
Allowed: r.Allowed,
AuditAnnotations: r.AuditAnnotations,
Patch: r.Patch,
PatchType: pt,
Result: r.Result,
Warnings: r.Warnings,
}
}
func convertAdmissionResponseToV1beta1(r *v1.AdmissionResponse) *v1beta1.AdmissionResponse {
var pt *v1beta1.PatchType
if r.PatchType != nil {

View File

@@ -40,7 +40,6 @@ func admitPods(ar v1.AdmissionReview) *v1.AdmissionResponse {
switch ar.Request.Operation {
case v1.Create:
from, _ := json.Marshal(pod)
fmt.Println(ar.String())
var found bool
for i := 0; i < len(pod.Spec.Containers); i++ {
if pod.Spec.Containers[i].Name == config.ContainerSidecarVPN {
@@ -151,41 +150,3 @@ func applyPodPatch(ar v1.AdmissionReview, shouldPatchPod func(*corev1.Pod) bool,
}
return &reviewResponse
}
// denySpecificAttachment denies `kubectl attach to-be-attached-pod -i -c=container1"
// or equivalent client requests.
func denySpecificAttachment(ar v1.AdmissionReview) *v1.AdmissionResponse {
klog.V(2).Info("handling attaching pods")
if ar.Request.Name != "to-be-attached-pod" {
return &v1.AdmissionResponse{Allowed: true}
}
podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
if e, a := podResource, ar.Request.Resource; e != a {
err := fmt.Errorf("expect resource to be %s, got %s", e, a)
klog.Error(err)
return toV1AdmissionResponse(err)
}
if e, a := "attach", ar.Request.SubResource; e != a {
err := fmt.Errorf("expect subresource to be %s, got %s", e, a)
klog.Error(err)
return toV1AdmissionResponse(err)
}
raw := ar.Request.Object.Raw
podAttachOptions := corev1.PodAttachOptions{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(raw, nil, &podAttachOptions); err != nil {
klog.Error(err)
return toV1AdmissionResponse(err)
}
klog.V(2).Info(fmt.Sprintf("podAttachOptions=%#v\n", podAttachOptions))
if !podAttachOptions.Stdin || podAttachOptions.Container != "container1" {
return &v1.AdmissionResponse{Allowed: true}
}
return &v1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Message: "attaching to pod 'to-be-attached-pod' is not allowed",
},
}
}