Skip to content
This repository was archived by the owner on Mar 16, 2024. It is now read-only.

Commit 05d349b

Browse files
Merge pull request #1890 from ibuildthecloud/main
Add image granted permissions
2 parents bc2a23d + 5401fda commit 05d349b

File tree

81 files changed

+891
-252
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+891
-252
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ replace (
1313
require (
1414
cuelang.org/go v0.5.0
1515
github.com/AlecAivazis/survey/v2 v2.3.6
16-
github.com/acorn-io/aml v0.0.0-20230619192500-1f56a8955db2
16+
github.com/acorn-io/aml v0.0.0-20230707003008-f4b3216ff21f
1717
github.com/acorn-io/baaah v0.0.0-20230628211933-3f682344a78d
1818
github.com/acorn-io/mink v0.0.0-20230523184405-ceaaa366d500
1919
github.com/acorn-io/namegenerator v0.0.0-20220915160418-9e3d5a0ffe78

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY
9292
github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE=
9393
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
9494
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
95-
github.com/acorn-io/aml v0.0.0-20230619192500-1f56a8955db2 h1:tWz51cHGC6GURkKqA4PdG3ObHz2YBrVzCfxXacNUqVY=
96-
github.com/acorn-io/aml v0.0.0-20230619192500-1f56a8955db2/go.mod h1:UEx5RRLFjryCEHN2pM59+d8A0mPJ3VAxggJOTzPymwg=
95+
github.com/acorn-io/aml v0.0.0-20230707003008-f4b3216ff21f h1:50i67wGaxqHzjBAQ0OTJi83mzWqOntKSn9snL7DvpXA=
96+
github.com/acorn-io/aml v0.0.0-20230707003008-f4b3216ff21f/go.mod h1:UEx5RRLFjryCEHN2pM59+d8A0mPJ3VAxggJOTzPymwg=
9797
github.com/acorn-io/baaah v0.0.0-20230628211933-3f682344a78d h1:a+geMqB3U52a4+iMmLZ9R/EXkgxrp0QCetoqLAUnTD8=
9898
github.com/acorn-io/baaah v0.0.0-20230628211933-3f682344a78d/go.mod h1:LtwaWrYK/VuGptWxeD5Sgl0sgJV1ksicpTzyLilow1U=
9999
github.com/acorn-io/mink v0.0.0-20230523184405-ceaaa366d500 h1:tiM36bM+iMWuW9HM+YlM1GfNDXC7f565z8Be5epO0qM=

integration/build/build_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestBuildDev(t *testing.T) {
3030
c := helper.BuilderClient(t, system.DefaultUserNamespace)
3131
img, err := c.AcornImageBuild(helper.GetCTX(t), "./testdata/dev/Acornfile", &client.AcornImageBuildOptions{
3232
Cwd: "./testdata/dev",
33-
Profiles: []string{"dev"},
33+
Profiles: []string{"devMode"},
3434
})
3535
assert.NoError(t, err)
3636
_, ok := img.ImageData.Containers["default"]

pkg/apis/internal.acorn.io/v1/appinstance.go

+52-31
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package v1
44

55
import (
6+
"strings"
7+
68
corev1 "k8s.io/api/core/v1"
79
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
810
)
@@ -83,26 +85,31 @@ const (
8385
)
8486

8587
type AppInstanceSpec struct {
86-
Region string `json:"region,omitempty"`
87-
Labels []ScopedLabel `json:"labels,omitempty"`
88-
Annotations []ScopedLabel `json:"annotations,omitempty"`
89-
Image string `json:"image,omitempty"`
90-
Stop *bool `json:"stop,omitempty"`
91-
Profiles []string `json:"profiles,omitempty"`
92-
Volumes []VolumeBinding `json:"volumes,omitempty"`
93-
Secrets []SecretBinding `json:"secrets,omitempty"`
94-
Environment []NameValue `json:"environment,omitempty"`
95-
PublishMode PublishMode `json:"publishMode,omitempty"`
96-
TargetNamespace string `json:"targetNamespace,omitempty"`
97-
Links []ServiceBinding `json:"services,omitempty"`
98-
Publish []PortBinding `json:"ports,omitempty"`
99-
DeployArgs GenericMap `json:"deployArgs,omitempty"`
100-
Permissions []Permissions `json:"permissions,omitempty"`
101-
AutoUpgrade *bool `json:"autoUpgrade,omitempty"`
102-
NotifyUpgrade *bool `json:"notifyUpgrade,omitempty"`
103-
AutoUpgradeInterval string `json:"autoUpgradeInterval,omitempty"`
104-
ComputeClasses ComputeClassMap `json:"computeClass,omitempty"`
105-
Memory MemoryMap `json:"memory,omitempty"`
88+
Region string `json:"region,omitempty"`
89+
Labels []ScopedLabel `json:"labels,omitempty"`
90+
Annotations []ScopedLabel `json:"annotations,omitempty"`
91+
Image string `json:"image,omitempty"`
92+
Stop *bool `json:"stop,omitempty"`
93+
Profiles []string `json:"profiles,omitempty"`
94+
Volumes []VolumeBinding `json:"volumes,omitempty"`
95+
Secrets []SecretBinding `json:"secrets,omitempty"`
96+
Environment []NameValue `json:"environment,omitempty"`
97+
PublishMode PublishMode `json:"publishMode,omitempty"`
98+
TargetNamespace string `json:"targetNamespace,omitempty"`
99+
Links []ServiceBinding `json:"services,omitempty"`
100+
Publish []PortBinding `json:"ports,omitempty"`
101+
DeployArgs GenericMap `json:"deployArgs,omitempty"`
102+
Permissions []Permissions `json:"permissions,omitempty"`
103+
ImageGrantedPermissions []Permissions `json:"imageGrantedPermissions,omitempty"`
104+
AutoUpgrade *bool `json:"autoUpgrade,omitempty"`
105+
NotifyUpgrade *bool `json:"notifyUpgrade,omitempty"`
106+
AutoUpgradeInterval string `json:"autoUpgradeInterval,omitempty"`
107+
ComputeClasses ComputeClassMap `json:"computeClass,omitempty"`
108+
Memory MemoryMap `json:"memory,omitempty"`
109+
}
110+
111+
func (in *AppInstanceSpec) GetPermissions() []Permissions {
112+
return append(in.Permissions, in.ImageGrantedPermissions...)
106113
}
107114

108115
func (in *AppInstance) GetStopped() bool {
@@ -117,20 +124,34 @@ func (in *AppInstanceSpec) GetNotifyUpgrade() bool {
117124
return in.NotifyUpgrade != nil && *in.NotifyUpgrade
118125
}
119126

127+
func addProfile(profiles []string, toAdd string) []string {
128+
found := true
129+
optional := strings.HasSuffix(toAdd, "?")
130+
nonOptionalName := toAdd[:len(toAdd)-1]
131+
for _, profile := range profiles {
132+
if profile == toAdd {
133+
found = true
134+
break
135+
} else if optional && profile == nonOptionalName {
136+
found = true
137+
break
138+
}
139+
}
140+
if !found {
141+
return append([]string{toAdd}, profiles...)
142+
}
143+
return profiles
144+
}
145+
120146
func (in *AppInstanceSpec) GetProfiles(devMode bool) []string {
147+
profiles := in.Profiles
121148
if devMode {
122-
found := false
123-
for _, profile := range in.Profiles {
124-
if profile == "dev?" {
125-
found = true
126-
break
127-
}
128-
}
129-
if !found {
130-
return append([]string{"dev?"}, in.Profiles...)
131-
}
149+
profiles = addProfile(profiles, "devMode?")
150+
}
151+
if in.GetAutoUpgrade() {
152+
profiles = addProfile(profiles, "autoUpgrade?")
132153
}
133-
return in.Profiles
154+
return profiles
134155
}
135156

136157
type ServiceBindings []ServiceBinding

pkg/apis/internal.acorn.io/v1/appspec.go

+157-46
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,60 @@ type PolicyRule struct {
233233
Scopes []string `json:"scopes,omitempty"`
234234
}
235235

236+
func matches(allowed, requested []string, emptyAllowedIsAll bool) bool {
237+
for _, requested := range requested {
238+
if !matchesSingle(allowed, requested, emptyAllowedIsAll) {
239+
return false
240+
}
241+
}
242+
return true
243+
}
244+
245+
func matchesSingle(allowed []string, requested string, emptyAllowedIsAll bool) bool {
246+
if len(requested) == 0 {
247+
return true
248+
}
249+
if emptyAllowedIsAll && len(allowed) == 0 {
250+
return true
251+
}
252+
for _, allow := range allowed {
253+
if allow == "*" || requested == allow {
254+
return true
255+
}
256+
if strings.HasSuffix(allow, "*") && strings.HasPrefix(requested, allow[:len(allow)-1]) {
257+
return true
258+
}
259+
}
260+
261+
return false
262+
}
263+
264+
func (p PolicyRule) Grants(currentNamespace string, requested PolicyRule) bool {
265+
if len(p.NonResourceURLs) > 0 && len(p.Resources) == 0 {
266+
return len(p.Scopes) == 0 &&
267+
len(requested.Scopes) == 0 &&
268+
matches(p.NonResourceURLs, requested.NonResourceURLs, false)
269+
}
270+
271+
if len(p.NonResourceURLs) > 0 {
272+
return false
273+
}
274+
275+
for _, ns := range p.ResolveNamespaces(currentNamespace) {
276+
for _, requestedNamespace := range requested.ResolveNamespaces(currentNamespace) {
277+
if ns == requestedNamespace &&
278+
matches(p.Verbs, requested.Verbs, false) &&
279+
matches(p.APIGroups, requested.APIGroups, false) &&
280+
matches(p.Resources, requested.Resources, false) &&
281+
matches(p.ResourceNames, requested.ResourceNames, true) {
282+
return true
283+
}
284+
}
285+
}
286+
287+
return false
288+
}
289+
236290
func (p PolicyRule) IsAccountScoped() bool {
237291
for _, scope := range p.Scopes {
238292
if scope == "" {
@@ -289,13 +343,38 @@ func (p PolicyRule) Namespaces() (result []string) {
289343
return
290344
}
291345

346+
func GroupByServiceName(perms []Permissions) map[string]Permissions {
347+
byServiceName := map[string]Permissions{}
348+
349+
for _, perm := range perms {
350+
existing := byServiceName[perm.ServiceName]
351+
existing.ServiceName = perm.ServiceName
352+
existing.Rules = append(existing.Rules, perm.Rules...)
353+
byServiceName[perm.ServiceName] = existing
354+
}
355+
356+
return byServiceName
357+
}
358+
292359
type Permissions struct {
293360
ServiceName string `json:"serviceName,omitempty"`
294361
Rules []PolicyRule `json:"rules,omitempty"`
295362
// Deprecated, use Rules with the 'scopes: ["cluster"]' field
296363
ZZ_ClusterRules []PolicyRule `json:"clusterRules,omitempty"`
297364
}
298365

366+
func (in Permissions) Grants(currentNamespace string, forService string, requested PolicyRule) bool {
367+
if in.ServiceName != forService {
368+
return false
369+
}
370+
for _, granted := range in.GetRules() {
371+
if granted.Grants(currentNamespace, requested) {
372+
return true
373+
}
374+
}
375+
return false
376+
}
377+
299378
func (in Permissions) GetRules() []PolicyRule {
300379
result := in.Rules
301380
for _, rule := range in.ZZ_ClusterRules {
@@ -321,13 +400,27 @@ func (in *Permissions) Get() Permissions {
321400
return *in
322401
}
323402

324-
func FindPermission(serviceName string, perms []Permissions) Permissions {
403+
func Grants(grantedPermissions Permissions, currentNamespace string, requestedPermissions Permissions) (missing Permissions, granted bool) {
404+
missing.ServiceName = requestedPermissions.ServiceName
405+
406+
for _, requested := range requestedPermissions.Rules {
407+
if grantedPermissions.Grants(currentNamespace, requestedPermissions.ServiceName, requested) {
408+
continue
409+
}
410+
missing.Rules = append(missing.Rules, requested)
411+
}
412+
413+
return missing, len(missing.Rules) == 0
414+
}
415+
416+
func FindPermission(serviceName string, perms []Permissions) (result Permissions) {
417+
result.ServiceName = serviceName
325418
for _, perm := range perms {
326-
if serviceName == perm.ServiceName {
327-
return perm
419+
if perm.ServiceName == serviceName {
420+
result.Rules = append(result.Rules, perm.GetRules()...)
328421
}
329422
}
330-
return Permissions{}
423+
return
331424
}
332425

333426
type Files map[string]File
@@ -418,24 +511,33 @@ type Router struct {
418511
Routes Routes `json:"routes,omitempty"`
419512
}
420513

514+
func (in Acorn) GetOriginalImage() string {
515+
originalImage := in.Image
516+
if in.Build != nil && in.Build.OriginalImage != "" {
517+
originalImage = in.Build.OriginalImage
518+
}
519+
return originalImage
520+
}
521+
421522
type Acorn struct {
422-
Labels ScopedLabels `json:"labels,omitempty"`
423-
Annotations ScopedLabels `json:"annotations,omitempty"`
424-
Image string `json:"image,omitempty"`
425-
Build *AcornBuild `json:"build,omitempty"`
426-
Profiles []string `json:"profiles,omitempty"`
427-
DeployArgs GenericMap `json:"deployArgs,omitempty"`
428-
Publish PortBindings `json:"publish,omitempty"`
429-
PublishMode PublishMode `json:"publishMode,omitempty"`
430-
Environment NameValues `json:"environment,omitempty"`
431-
Secrets SecretBindings `json:"secrets,omitempty"`
432-
Volumes VolumeBindings `json:"volumes,omitempty"`
433-
Links ServiceBindings `json:"links,omitempty"`
434-
AutoUpgrade *bool `json:"autoUpgrade,omitempty"`
435-
NotifyUpgrade *bool `json:"notifyUpgrade,omitempty"`
436-
AutoUpgradeInterval string `json:"autoUpgradeInterval,omitempty"`
437-
Memory MemoryMap `json:"memory,omitempty"`
438-
ComputeClasses ComputeClassMap `json:"computeClasses,omitempty"`
523+
Labels ScopedLabels `json:"labels,omitempty"`
524+
Annotations ScopedLabels `json:"annotations,omitempty"`
525+
Image string `json:"image,omitempty"`
526+
Build *AcornBuild `json:"build,omitempty"`
527+
Profiles []string `json:"profiles,omitempty"`
528+
DeployArgs GenericMap `json:"deployArgs,omitempty"`
529+
Publish PortBindings `json:"publish,omitempty"`
530+
PublishMode PublishMode `json:"publishMode,omitempty"`
531+
Environment NameValues `json:"environment,omitempty"`
532+
Secrets SecretBindings `json:"secrets,omitempty"`
533+
Volumes VolumeBindings `json:"volumes,omitempty"`
534+
Links ServiceBindings `json:"links,omitempty"`
535+
AutoUpgrade *bool `json:"autoUpgrade,omitempty"`
536+
NotifyUpgrade *bool `json:"notifyUpgrade,omitempty"`
537+
AutoUpgradeInterval string `json:"autoUpgradeInterval,omitempty"`
538+
Memory MemoryMap `json:"memory,omitempty"`
539+
ComputeClasses ComputeClassMap `json:"computeClasses,omitempty"`
540+
Permissions map[string]Permissions `json:"permissions,omitempty"`
439541
}
440542

441543
type Secret struct {
@@ -474,31 +576,40 @@ type GeneratedService struct {
474576
}
475577

476578
type Service struct {
477-
Labels ScopedLabels `json:"labels,omitempty"`
478-
Annotations ScopedLabels `json:"annotations,omitempty"`
479-
Default bool `json:"default,omitempty"`
480-
External string `json:"external,omitempty"`
481-
Alias string `json:"alias,omitempty"`
482-
Address string `json:"address,omitempty"`
483-
Ports Ports `json:"ports,omitempty"`
484-
Container string `json:"container,omitempty"`
485-
Data GenericMap `json:"data,omitempty"`
486-
Generated *GeneratedService `json:"generated,omitempty"`
487-
Image string `json:"image,omitempty"`
488-
Build *AcornBuild `json:"build,omitempty"`
489-
ServiceArgs GenericMap `json:"serviceArgs,omitempty"`
490-
Environment NameValues `json:"environment,omitempty"`
491-
Secrets SecretBindings `json:"secrets,omitempty"`
492-
Links ServiceBindings `json:"links,omitempty"`
493-
AutoUpgrade *bool `json:"autoUpgrade,omitempty"`
494-
NotifyUpgrade *bool `json:"notifyUpgrade,omitempty"`
495-
AutoUpgradeInterval string `json:"autoUpgradeInterval,omitempty"`
496-
Memory MemoryMap `json:"memory,omitempty"`
497-
}
498-
499-
func (s Service) GetJob() string {
500-
if s.Generated == nil {
579+
Labels ScopedLabels `json:"labels,omitempty"`
580+
Annotations ScopedLabels `json:"annotations,omitempty"`
581+
Default bool `json:"default,omitempty"`
582+
External string `json:"external,omitempty"`
583+
Alias string `json:"alias,omitempty"`
584+
Address string `json:"address,omitempty"`
585+
Ports Ports `json:"ports,omitempty"`
586+
Container string `json:"container,omitempty"`
587+
Data GenericMap `json:"data,omitempty"`
588+
Generated *GeneratedService `json:"generated,omitempty"`
589+
Image string `json:"image,omitempty"`
590+
Build *AcornBuild `json:"build,omitempty"`
591+
ServiceArgs GenericMap `json:"serviceArgs,omitempty"`
592+
Environment NameValues `json:"environment,omitempty"`
593+
Secrets SecretBindings `json:"secrets,omitempty"`
594+
Links ServiceBindings `json:"links,omitempty"`
595+
AutoUpgrade *bool `json:"autoUpgrade,omitempty"`
596+
NotifyUpgrade *bool `json:"notifyUpgrade,omitempty"`
597+
AutoUpgradeInterval string `json:"autoUpgradeInterval,omitempty"`
598+
Memory MemoryMap `json:"memory,omitempty"`
599+
Permissions map[string]Permissions `json:"permissions,omitempty"`
600+
}
601+
602+
func (in Service) GetOriginalImage() string {
603+
originalImage := in.Image
604+
if in.Build != nil && in.Build.OriginalImage != "" {
605+
originalImage = in.Build.OriginalImage
606+
}
607+
return originalImage
608+
}
609+
610+
func (in Service) GetJob() string {
611+
if in.Generated == nil {
501612
return ""
502613
}
503-
return s.Generated.Job
614+
return in.Generated.Job
504615
}

pkg/apis/internal.acorn.io/v1/unmarshal.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,8 @@ func ParseNameValues(fillEnv bool, s ...string) (result []NameValue) {
13681368
for _, s := range s {
13691369
k, v, _ := strings.Cut(s, "=")
13701370
if v == "" && fillEnv {
1371-
v = os.Getenv(k)
1371+
parts := strings.Split(k, ".")
1372+
v = os.Getenv(parts[len(parts)-1])
13721373
}
13731374
result = append(result, NameValue{
13741375
Name: k,

0 commit comments

Comments
 (0)