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.
* Make non-API Kind structures common types in Cedar Schema * Look up each referenced type in an attribute to tell if its an entity or type Signed-off-by: Micah Hausler <mhausler@amazon.com>
- Loading branch information
1 parent
fbedd22
commit 3b8b4f5
Showing
20 changed files
with
10,313 additions
and
11,495 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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,67 @@ | ||
package convert | ||
|
||
import ( | ||
"slices" | ||
"strings" | ||
) | ||
|
||
func ParseSchemaName(schemaName string) (ns, apiGroup, version, kind string) { | ||
schemaName = strings.ReplaceAll(schemaName, "-", "_") | ||
strs := strings.Split(schemaName, ".") | ||
if len(strs) < 4 { | ||
return | ||
} | ||
slices.Reverse(strs) | ||
|
||
if strings.HasPrefix(schemaName, "io.k8s.api.") { | ||
strs = strs[:len(strs)-3] | ||
} else if strings.HasPrefix(schemaName, "io.k8s.apimachinery.pkg.apis.meta") { | ||
strs = strs[:len(strs)-4] | ||
} else { | ||
nsParts := strs[3:] | ||
slices.Reverse(nsParts) | ||
ns = strings.Join(nsParts, "::") | ||
} | ||
|
||
kind = strs[0] | ||
version = strs[1] | ||
apiGroup = strs[2] | ||
return | ||
} | ||
|
||
func SchemaNameToCedar(schemaName string) (ns, typeName string) { | ||
ns, apiGroup, version, kind := ParseSchemaName(schemaName) | ||
if ns != "" { | ||
return strings.Join([]string{ns, apiGroup, version}, "::"), kind | ||
} | ||
return strings.Join([]string{apiGroup, version}, "::"), kind | ||
} | ||
|
||
// Transform `"#/components/schemas/io.k8s.api.apps.v1.DaemonSetSpec"` | ||
// into `apps::v1::DaemonSetSpec` | ||
func refToRelativeTypeName(current, ref string) string { | ||
curParsed, found := strings.CutPrefix(current, "#/components/schemas/") | ||
if !found { | ||
curParsed = current | ||
} | ||
currentNs, _ := SchemaNameToCedar(curParsed) | ||
|
||
refParsed, found := strings.CutPrefix(ref, "#/components/schemas/") | ||
if !found { | ||
refParsed = ref | ||
} | ||
refNs, refType := SchemaNameToCedar(refParsed) | ||
|
||
if (refNs == "meta::v1" && refType == "Time") || | ||
(refNs == "meta::v1" && refType == "MicroTime") || | ||
(refNs == "io::k8s::apimachinery::pkg::util::intstr" && refType == "IntOrString") || | ||
(refNs == "io::k8s::apimachinery::pkg::api::resource" && refType == "Quantity") || | ||
(refNs == "io::k8s::apimachinery::pkg::runtime" && refType == "RawExtension") { | ||
return "String" | ||
} | ||
|
||
if currentNs == refNs { | ||
return refType | ||
} | ||
return refNs + "::" + refType | ||
} |
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,205 @@ | ||
package convert | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestParseSchemaName(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
intput string | ||
wantNs, wantAPIGroup, wantVersion, wantKind string | ||
}{ | ||
{ | ||
"DaemonSet", | ||
"io.k8s.api.apps.v1.DaemonSet", | ||
"", | ||
"apps", | ||
"v1", | ||
"DaemonSet", | ||
}, | ||
{ | ||
"ConfigMap", | ||
"io.k8s.api.core.v1.ConfigMap", | ||
"", | ||
"core", | ||
"v1", | ||
"ConfigMap", | ||
}, | ||
{ | ||
"Cedar Policy", | ||
"aws.k8s.cedar.v1.Policy", | ||
"aws::k8s", | ||
"cedar", | ||
"v1", | ||
"Policy", | ||
}, | ||
{ | ||
"too short", | ||
"aws.cedar.v1", | ||
"", | ||
"", | ||
"", | ||
"", | ||
}, | ||
{ | ||
"Object meta", | ||
"io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta", | ||
"", | ||
"meta", | ||
"v1", | ||
"ObjectMeta", | ||
}, | ||
{ | ||
"CRD", | ||
"io.cert-manager.v1.ClusterIssuer", | ||
"io", | ||
"cert_manager", | ||
"v1", | ||
"ClusterIssuer", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
gotNs, gotAPIGroup, gotVersion, gotKind := ParseSchemaName(tc.intput) | ||
if gotNs != tc.wantNs { | ||
t.Fatalf("unexpected ns: got %q, want %q", gotNs, tc.wantNs) | ||
} | ||
if gotAPIGroup != tc.wantAPIGroup { | ||
t.Fatalf("unexpected apigroup: got %q, want %q", gotAPIGroup, tc.wantAPIGroup) | ||
} | ||
if gotVersion != tc.wantVersion { | ||
t.Fatalf("unexpected version: got %q, want %q", gotVersion, tc.wantVersion) | ||
} | ||
if gotKind != tc.wantKind { | ||
t.Fatalf("unexpected kind: got %q, want %q", gotKind, tc.wantKind) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestSchemaNameToCedar(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
input string | ||
wantNs, wantName string | ||
}{ | ||
{ | ||
"K8s auth api", | ||
"io.k8s.api.authentication.v1.TokenRequest", | ||
"authentication::v1", | ||
"TokenRequest", | ||
}, | ||
{ | ||
"K8s autoscaling API", | ||
"io.k8s.api.autoscaling.v1.Scale", | ||
"autoscaling::v1", | ||
"Scale", | ||
}, | ||
{ | ||
"core K8s api", | ||
"io.k8s.api.core.v1.ConfigMap", | ||
"core::v1", | ||
"ConfigMap", | ||
}, | ||
{ | ||
"coordination K8s api", | ||
"io.k8s.api.coordination.v1.Lease", | ||
"coordination::v1", | ||
"Lease", | ||
}, | ||
{ | ||
"k8s meta API", | ||
"io.k8s.apimachinery.pkg.apis.meta.v1.Status", | ||
"meta::v1", | ||
"Status", | ||
}, | ||
// Should never get this case, we filter it out elsewhere | ||
// { | ||
// "k8s resoruce API", | ||
// "io.k8s.apimachinery.pkg.api.resource.Quantity", | ||
// "api::resource", | ||
// "Quantity", | ||
// }, | ||
{ | ||
"Cedar policy resource", | ||
"aws.k8s.cedar.v1.Policy", | ||
"aws::k8s::cedar::v1", | ||
"Policy", | ||
}, | ||
} | ||
|
||
for _, tc := range cases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
gotNs, gotName := SchemaNameToCedar(tc.input) | ||
if gotNs != tc.wantNs { | ||
t.Fatalf("unexpected ns: got %q, want %q", gotNs, tc.wantNs) | ||
} | ||
if gotName != tc.wantName { | ||
t.Fatalf("unexpected name: got %q, want %q", gotName, tc.wantName) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestRefToRelativeTypeName(t *testing.T) { | ||
cases := []struct { | ||
name, input, currentNs, want string | ||
}{ | ||
{ | ||
name: "CRD", | ||
input: `#/components/schemas/aws.k8s.cedar.v1.Policy`, | ||
want: "aws::k8s::cedar::v1::Policy", | ||
}, | ||
{ | ||
name: "K8s API", | ||
input: `#/components/schemas/io.k8s.api.core.v1.ConfigMap`, | ||
want: "core::v1::ConfigMap", | ||
}, | ||
{ | ||
name: "Meta API", | ||
input: `#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta`, | ||
want: "meta::v1::ObjectMeta", | ||
}, | ||
{ | ||
name: "in-tree API group", | ||
input: `#/components/schemas/io.k8s.api.apps.v1.DaemonSet`, | ||
want: "apps::v1::DaemonSet", | ||
}, | ||
{ | ||
name: "in-tree API group, same namespace", | ||
input: `#/components/schemas/io.k8s.api.core.v1.PodSpec`, | ||
currentNs: "#/components/schemas/io.k8s.api.core.v1.Pod", | ||
want: "PodSpec", | ||
}, | ||
{ | ||
name: "Time to string", | ||
input: `#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time`, | ||
want: "String", | ||
}, | ||
{ | ||
name: "MicroTime to string", | ||
input: `#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime`, | ||
want: "String", | ||
}, | ||
{ | ||
name: "Quantity to string", | ||
input: `#/components/schemas/io.k8s.apimachinery.pkg.api.resource.Quantity`, | ||
want: "String", | ||
}, | ||
{ | ||
name: "RawExtension to String", | ||
input: `#/components/schemas/io.k8s.apimachinery.pkg.runtime.RawExtension`, | ||
want: "String", | ||
}, | ||
} | ||
for _, tc := range cases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
got := refToRelativeTypeName(tc.currentNs, tc.input) | ||
if got != tc.want { | ||
t.Fatalf("unexpected output: got %q, want %q", got, tc.want) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.