Skip to content

Commit

Permalink
support new resource (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
aatarasoff authored Sep 5, 2022
1 parent 6497b6d commit 1228c4a
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 67 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
.values.yml
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ Simplify the Linkerd Authorization Policies management according to [the article
| 2.11.x | 0.1.0 - 0.4.0 |
| 2.12.x | \>= 0.5.0 |

New `AuthorizationPolicy` and `HTTPRoute` are in WIP. Their support will be soon.
New `AuthorizationPolicy` are supported since `0.6.0`.

New `HTTPRoute` are in WIP. Its support will be soon.

## How to use it

Expand All @@ -22,7 +24,7 @@ linkerd easyauth [COMMAND] -n <namespace> [FLAGS]
```

### Supported commands
- `authcheck`: checks for obsolete `Server` and `ServerAuthorization` resources, checks that PODs ports have `Server` resource
- `authcheck`: checks for obsolete `Server` and policies resources like `ServerAuthorization` and `AuthorizationPolicy`, checks that PODs ports have `Server` resource
- `list`: list of Pods that were injected by `linkerd.io/easyauth-enabled: true` annotation (more information below)
- `authz`: fast implementation for fetch the list server authorizations for a resource (use caching)

Expand All @@ -40,7 +42,7 @@ Install the helm chart with injector and policies:
### What the helm chart provides
- Injector that adds `linkerd.io/easyauth-enabled: true` label for all meshed pods (you can limit namespaces via helmchart)
- `Server` in terms of Linkerd authorization policies for `linkerd-admin-port`
- `ServerAuthorization` resources that provides basic allow policies for ingress, Linkerd itself, and monitoring
- `AuthorizationPolicy` resources that provides basic allow policies for ingress, Linkerd itself, and monitoring

### What the helm chart does not provide
Because the `Server` should be one per service per port, we can define the server for the linkerd proxy admin port only.
Expand All @@ -63,7 +65,7 @@ spec:

### Important Values
#### Meshed Apps Namespaces
Because all `ServerAuthorization` policies are Namespaced scope then we should add common policies to each namespace with our apps:
Because all `AuthorizationPolicy` policies are Namespaced scope then we should add common policies to each namespace with our apps:
```
meshedApps:
namespaces:
Expand Down
4 changes: 2 additions & 2 deletions charts/linkerd-easyauth/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: v1
appVersion: "0.5.0"
appVersion: "0.6.0"
description: A Helm chart for Linkerd easyauth extension.
name: linkerd-easyauth
version: "0.5.0"
version: "0.6.0"
99 changes: 57 additions & 42 deletions charts/linkerd-easyauth/templates/auth-policies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,87 @@ kind: Server
metadata:
namespace: {{ . }}
name: linkerd-admin-port
labels:
linkerd.io/server-type: common
spec:
podSelector:
matchLabels:
linkerd.io/easyauth: true
linkerd.io/easyauth: "true"
port: linkerd-admin
---
apiVersion: policy.linkerd.io/v1beta1
kind: Server
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
namespace: {{ . }}
name: app-serving-port
labels:
linkerd.io/server-type: common
name: linkerd-authn
spec:
podSelector:
matchLabels:
linkerd.io/easyauth: true
port: linkerd-admin
identities:
{{- range $.Values.policies.linkerd.namespaces }}
- "*.{{ . }}.serviceaccount.identity.linkerd.cluster.local"
{{- end }}
---
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
namespace: {{ . }}
name: linkerd-admin-allow
spec:
server:
targetRef:
group: policy.linkerd.io
kind: Server
name: linkerd-admin-port
client:
meshTLS:
identities:
{{- range $.Values.policies.linkerd.namespaces }}
- "*.{{ . }}.serviceaccount.identity.linkerd.cluster.local"
{{- end }}
---
requiredAuthenticationRefs:
- name: linkerd-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
{{- if $.Values.policies.monitoring.enabled }}
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
namespace: {{ . }}
name: monitoring-authn
spec:
identities:
- "*.{{ $.Values.policies.monitoring.namespace }}.serviceaccount.identity.linkerd.cluster.local"
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
namespace: {{ . }}
name: linkerd-monitoring-allow
spec:
server:
selector:
matchLabels:
linkerd.io/server-type: common
client:
meshTLS:
identities:
- "*.{{ $.Values.policies.monitoring.namespace }}.serviceaccount.identity.linkerd.cluster.local"
targetRef:
group: core
kind: Namespace
name: {{ . }}
requiredAuthenticationRefs:
- name: monitoring-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
{{ end }}
{{- if $.Values.policies.ingress.enabled }}
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
namespace: {{ . }}
name: ingress-authn
spec:
identities:
- "*.{{ $.Values.policies.ingress.namespace }}.serviceaccount.identity.linkerd.cluster.local"
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
namespace: {{ . }}
name: linkerd-ingress-allow
spec:
server:
selector:
matchLabels:
linkerd.io/server-type: common
client:
meshTLS:
identities:
- "*.{{ $.Values.policies.ingress.namespace }}.serviceaccount.identity.linkerd.cluster.local"
targetRef:
group: core
kind: Namespace
name: {{ . }}
requiredAuthenticationRefs:
- name: ingress-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
{{ end }}
{{ end }}
2 changes: 1 addition & 1 deletion charts/linkerd-easyauth/templates/easyauth-injector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ metadata:
name: easyauth-injector
namespace: {{.Values.namespace}}
spec:
replicas: 1
replicas: {{ .Values.webhook.replicas }}
selector:
matchLabels:
linkerd.io/extension: easyauth
Expand Down
5 changes: 4 additions & 1 deletion charts/linkerd-easyauth/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ tolerations: &default_tolerations
webhook:
image:
name: aatarasoff/linkerd-easyauth-webhook
version: 0.1.0
version: 0.6.0
pullPolicy: IfNotPresent

# modify to HA mode
replicas: 1

logLevel: info

failurePolicy: Fail
Expand Down
41 changes: 36 additions & 5 deletions cmd/authcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,14 @@ func easyAuthCategory(resources *K8sResources) *healthcheck.Category {
checkers := []healthcheck.Checker{}

checkers = append(checkers,
*healthcheck.NewChecker("linkerd-easyauth no Server without ServerAuthorizations").
*healthcheck.NewChecker("linkerd-easyauth no Server without authorization policies").
Warning().
WithCheck(func(ctx context.Context) error {
serversWOServerAuthorizations := []string{}

for _, server := range resources.Servers {
founded := false

for _, serverAuthorization := range resources.ServerAuthorizations {
selector, err := metav1.LabelSelectorAsSelector(serverAuthorization.Spec.Server.Selector)
if err != nil {
Expand All @@ -105,19 +106,30 @@ func easyAuthCategory(resources *K8sResources) *healthcheck.Category {
}
}

for _, policy := range resources.AuthorizationPolicies {
// namespaced policies applies on each server
if policy.Spec.TargetRef.Kind == "Namespace" {
founded = true
}

if string(policy.Spec.TargetRef.Name) == server.GetName() {
founded = true
}
}

if !founded {
serversWOServerAuthorizations = append(serversWOServerAuthorizations, fmt.Sprintf("Server %s has no ServerAuthorizarions", server.GetName()))
serversWOServerAuthorizations = append(serversWOServerAuthorizations, fmt.Sprintf("Server %s has no authorization policies", server.GetName()))
}
}

if len(serversWOServerAuthorizations) == 0 {
return nil
}
return fmt.Errorf("Some servers have no ServerAuthorizations:\n\t%s", strings.Join(serversWOServerAuthorizations, "\n\t"))
return fmt.Errorf("Some servers have no authorization policies:\n\t%s", strings.Join(serversWOServerAuthorizations, "\n\t"))
}))

checkers = append(checkers,
*healthcheck.NewChecker("linkerd-easyauth no ServerAuthorizations without Server").
*healthcheck.NewChecker("linkerd-easyauth no authorization policies without Server").
Warning().
WithCheck(func(ctx context.Context) error {
serverAuthorizationsWOServer := []string{}
Expand All @@ -140,7 +152,26 @@ func easyAuthCategory(resources *K8sResources) *healthcheck.Category {
}

if !founded {
serverAuthorizationsWOServer = append(serverAuthorizationsWOServer, fmt.Sprintf("ServerAuthorizarions %s do not apply to any Server", serverAuthorization.GetName()))
serverAuthorizationsWOServer = append(serverAuthorizationsWOServer, fmt.Sprintf("ServerAuthorizarions %s does not apply to any Server", serverAuthorization.GetName()))
}
}

for _, policy := range resources.AuthorizationPolicies {
founded := false

if policy.Spec.TargetRef.Kind == "Namespace" {
// at least one Server should exist
founded = len(resources.Servers) > 0
} else {
for _, server := range resources.Servers {
if policy.Spec.TargetRef.Kind == "Server" && (string(policy.Spec.TargetRef.Name) == server.GetName()) {
founded = true
}
}
}

if !founded {
serverAuthorizationsWOServer = append(serverAuthorizationsWOServer, fmt.Sprintf("Authorization Policy %s does not apply to any Server", policy.GetName()))
}
}

Expand Down
31 changes: 21 additions & 10 deletions cmd/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package cmd
import (
"context"
"fmt"
"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta1"
beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
policy "github.com/linkerd/linkerd2/controller/gen/apis/policy/v1alpha1"
server "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta1"
saz "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
l5dcrdinformer "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions"
pkgK8s "github.com/linkerd/linkerd2/controller/k8s"
"github.com/linkerd/linkerd2/pkg/k8s"
Expand All @@ -17,10 +18,11 @@ import (
)

type K8sResources struct {
Pods *v1.PodList
Services *v1.ServiceList
Servers []*v1beta1.Server
ServerAuthorizations []*beta1.ServerAuthorization
Pods *v1.PodList
Services *v1.ServiceList
Servers []*server.Server
ServerAuthorizations []*saz.ServerAuthorization
AuthorizationPolicies []*policy.AuthorizationPolicy
}

func FetchK8sResources(ctx context.Context, namespace string) (*K8sResources, error) {
Expand Down Expand Up @@ -51,11 +53,17 @@ func FetchK8sResources(ctx context.Context, namespace string) (*K8sResources, er
return nil, err
}

authorizationPolicies, err := lr5dAPI.Policy().V1alpha1().AuthorizationPolicies().Lister().AuthorizationPolicies(namespace).List(labels.NewSelector())
if err != nil {
return nil, err
}

return &K8sResources{
Pods: pods,
Services: services,
Servers: servers,
ServerAuthorizations: serverAuthorizations,
Pods: pods,
Services: services,
Servers: servers,
ServerAuthorizations: serverAuthorizations,
AuthorizationPolicies: authorizationPolicies,
}, nil
}

Expand All @@ -77,6 +85,9 @@ func initServerAPI(kubeconfigPath string) l5dcrdinformer.SharedInformerFactory {
stopCh := make(chan struct{})
go lr5dAPI.Server().V1beta1().Servers().Informer().Run(stopCh)
go lr5dAPI.Serverauthorization().V1beta1().ServerAuthorizations().Informer().Run(stopCh)
go lr5dAPI.Policy().V1alpha1().AuthorizationPolicies().Informer().Run(stopCh)
go lr5dAPI.Policy().V1alpha1().MeshTLSAuthentications().Informer().Run(stopCh)
go lr5dAPI.Policy().V1alpha1().NetworkAuthentications().Informer().Run(stopCh)

ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
Expand Down

0 comments on commit 1228c4a

Please sign in to comment.