|
|
|
@ -23,6 +23,54 @@ import (
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// checkSecretPermissions checks that the current pod has permission to read,
|
|
|
|
|
// write and patch secretName in the cluster.
|
|
|
|
|
func checkSecretPermissions(ctx context.Context, secretName string) error {
|
|
|
|
|
for _, verb := range []string{"get", "update", "patch"} {
|
|
|
|
|
sar := map[string]any{
|
|
|
|
|
"apiVersion": "authorization.k8s.io/v1",
|
|
|
|
|
"kind": "SelfSubjectAccessReview",
|
|
|
|
|
"spec": map[string]any{
|
|
|
|
|
"resourceAttributes": map[string]any{
|
|
|
|
|
"namespace": kubeNamespace,
|
|
|
|
|
"verb": verb,
|
|
|
|
|
"resource": "secrets",
|
|
|
|
|
"name": secretName,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
bs, err := json.Marshal(sar)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
req, err := http.NewRequest("POST", "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews", bytes.NewReader(bs))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
resp, err := doKubeRequest(ctx, req)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
bs, err = io.ReadAll(resp.Body)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
var res struct {
|
|
|
|
|
Status struct {
|
|
|
|
|
Allowed bool `json:"allowed"`
|
|
|
|
|
} `json:"status"`
|
|
|
|
|
}
|
|
|
|
|
if err := json.Unmarshal(bs, &res); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if !res.Status.Allowed {
|
|
|
|
|
return fmt.Errorf("missing permission: cannot %s secret %q", verb, secretName)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// findKeyInKubeSecret inspects the kube secret secretName for a data
|
|
|
|
|
// field called "authkey", and returns its value if present.
|
|
|
|
|
func findKeyInKubeSecret(ctx context.Context, secretName string) (string, error) {
|
|
|
|
@ -193,8 +241,8 @@ func doKubeRequest(ctx context.Context, r *http.Request) (*http.Response, error)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
|
return resp, fmt.Errorf("got non-200 status code %d", resp.StatusCode)
|
|
|
|
|
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
|
|
|
|
|
return resp, fmt.Errorf("got non-200/201 status code %d", resp.StatusCode)
|
|
|
|
|
}
|
|
|
|
|
return resp, nil
|
|
|
|
|
}
|
|
|
|
|