forked from awslabs/cedar-access-control-for-k8s
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4202289
commit b00602b
Showing
9 changed files
with
384 additions
and
219 deletions.
There are no files selected for viewing
This file contains 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 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,145 @@ | ||
package v1alpha1 | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
const ( | ||
StoreTypeDirectory = "directory" | ||
StoreTypeCRD = "crd" | ||
StoreTypeVerifiedPermissions = "verifiedPermissions" | ||
) | ||
|
||
type Duration time.Duration | ||
|
||
func (d Duration) MarshalJSON() ([]byte, error) { | ||
return json.Marshal(time.Duration(d).String()) | ||
} | ||
|
||
func (d *Duration) UnmarshalJSON(b []byte) error { | ||
var v interface{} | ||
if err := json.Unmarshal(b, &v); err != nil { | ||
return err | ||
} | ||
switch value := v.(type) { | ||
case float64: | ||
*d = Duration(time.Duration(value)) | ||
return nil | ||
case string: | ||
tmp, err := time.ParseDuration(value) | ||
if err != nil { | ||
return err | ||
} | ||
*d = Duration(tmp) | ||
return nil | ||
default: | ||
return errors.New("invalid duration") | ||
} | ||
} | ||
|
||
// +kubebuilder:object:root=true | ||
|
||
// CedarConfig is a type for storing Cedar webhook configuration data | ||
type CedarConfig struct { | ||
metav1.TypeMeta `json:",inline"` | ||
|
||
//+required | ||
Spec ConfigSpec `json:"spec"` | ||
} | ||
|
||
func (c *CedarConfig) Validate() error { | ||
for i, storeDef := range c.Spec.Stores { | ||
storeId := fmt.Sprintf(".spec.stores[%d]: ", i) | ||
err := storeDef.Validate() | ||
if err != nil { | ||
return errors.New(storeId + err.Error()) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
type ConfigSpec struct { | ||
//+required | ||
Stores []StoreConfig `json:"stores"` | ||
} | ||
|
||
type StoreConfig struct { | ||
//+kubebuilder:validation:Enum=directory;crd;verifiedPermissions | ||
//+required | ||
Type string `json:"type"` | ||
//+optional | ||
DirectoryStore DirectoryStoreConfig `json:"directoryStore,omitempty"` | ||
//+optional | ||
CRDStore CRDStoreConfig `json:"crdStore,omitempty"` | ||
//+optional | ||
VerifiedPermissionsStore VerifiedPermissionsStoreConfig `json:"verifiedPermissionsStore,omitempty"` | ||
} | ||
|
||
type DirectoryStoreConfig struct { | ||
//+required | ||
Path string `json:"path"` | ||
//+optional | ||
RefreshInterval *Duration `json:"refreshInterval,omitempty"` | ||
} | ||
|
||
type CRDStoreConfig struct { | ||
//+optional | ||
KubeconfigContext string `json:"kubeconfigContext,omitempty"` | ||
} | ||
|
||
type VerifiedPermissionsStoreConfig struct { | ||
//+required | ||
PolicyStoreID string `json:"policyStoreId"` | ||
//+optional | ||
RefreshInterval *Duration `json:"refreshInterval,omitempty"` | ||
//+optional | ||
AWSRegion string `json:"awsRegion,omitempty"` | ||
//+optional | ||
AWSProfile string `json:"awsProfile,omitempty"` | ||
} | ||
|
||
func (c *StoreConfig) Validate() error { | ||
switch c.Type { | ||
case StoreTypeDirectory: | ||
if c.DirectoryStore.Path == "" { | ||
return errors.New("directory store path is required") | ||
} | ||
if c.DirectoryStore.RefreshInterval != nil { | ||
if *c.DirectoryStore.RefreshInterval < Duration(time.Second*30) { | ||
return errors.New("directory store refresh interval must be at least 30s") | ||
} | ||
if *c.DirectoryStore.RefreshInterval > Duration(time.Hour*24*7) { | ||
return errors.New("directory store refresh interval must be under 1 week (168h)") | ||
} | ||
} else { | ||
defaultDur := Duration(time.Minute * 1) | ||
c.DirectoryStore.RefreshInterval = &defaultDur | ||
} | ||
case StoreTypeCRD: | ||
// no-op | ||
case StoreTypeVerifiedPermissions: | ||
if c.VerifiedPermissionsStore.PolicyStoreID == "" { | ||
return errors.New("verified permissions store policy store id is required") | ||
} | ||
if c.VerifiedPermissionsStore.RefreshInterval != nil { | ||
if *c.VerifiedPermissionsStore.RefreshInterval < Duration(time.Second*30) { | ||
return errors.New("verified permissions refresh interval must be at least 30s") | ||
} | ||
if *c.VerifiedPermissionsStore.RefreshInterval > Duration(time.Hour*24*7) { | ||
return errors.New("verified permissions refresh interval must be under 1 week (168h)") | ||
} | ||
} else { | ||
defaultDur := Duration(time.Minute * 5) | ||
c.VerifiedPermissionsStore.RefreshInterval = &defaultDur | ||
} | ||
|
||
default: | ||
return errors.New("invalid store type") | ||
} | ||
return nil | ||
} |
This file contains 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,80 @@ | ||
package v1alpha1_test | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
"time" | ||
|
||
"github.com/awslabs/cedar-access-control-for-k8s/api/v1alpha1" | ||
) | ||
|
||
func TestDurationJson(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
input []byte | ||
skipMarshal bool | ||
want v1alpha1.Duration | ||
wantErr error | ||
}{ | ||
{ | ||
name: "float64", | ||
input: []byte("60000000000.0"), | ||
skipMarshal: true, | ||
want: v1alpha1.Duration(time.Second * 60), | ||
}, | ||
{ | ||
name: "Duration string", | ||
input: []byte(`"59m0s"`), | ||
want: v1alpha1.Duration(time.Minute * 59), | ||
}, | ||
{ | ||
name: "invalid string", | ||
input: []byte(`"60x"`), | ||
wantErr: errors.New(`time: unknown unit "x" in duration "60x"`), | ||
}, | ||
{ | ||
name: "invalid type", | ||
input: []byte(`true`), | ||
wantErr: errors.New("invalid duration"), | ||
}, | ||
{ | ||
name: "invalid json", | ||
input: []byte(`{true}`), | ||
wantErr: errors.New("invalid character 't' looking for beginning of object key string"), | ||
}, | ||
} | ||
|
||
for _, tc := range cases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
var dur v1alpha1.Duration | ||
err := dur.UnmarshalJSON(tc.input) | ||
if err != nil { | ||
if tc.wantErr != nil { | ||
if err.Error() != tc.wantErr.Error() { | ||
t.Fatalf("UnmarshalJSON() error = '%v', wantErr '%v'", err, tc.wantErr) | ||
} | ||
return | ||
} | ||
t.Fatal(err) | ||
} | ||
if dur != tc.want { | ||
t.Fatalf("got %v, want %v", dur, tc.want) | ||
} | ||
|
||
if !tc.skipMarshal { | ||
got, err := dur.MarshalJSON() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if string(got) != string(tc.input) { | ||
t.Errorf("MarshalJSON() = %v, want %v", string(got), string(tc.input)) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func DurationPtr(d time.Duration) *v1alpha1.Duration { | ||
dur := v1alpha1.Duration(d) | ||
return &dur | ||
} |
This file contains 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 |
---|---|---|
|
@@ -37,4 +37,5 @@ var ( | |
|
||
func init() { | ||
SchemeBuilder.Register(&PolicyList{}, &Policy{}) | ||
SchemeBuilder.Register(&CedarConfig{}) | ||
} |
This file contains 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.