Skip to content

Commit

Permalink
Merge pull request #144 from davoustp/fixes#143
Browse files Browse the repository at this point in the history
Fixes #143
  • Loading branch information
raffaelespazzoli authored May 24, 2023
2 parents 6108e19 + 91adfb6 commit 3d8d95b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
34 changes: 34 additions & 0 deletions api/v1alpha1/policy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ package v1alpha1

import (
"context"
"errors"
"reflect"
"regexp"
"strings"

vault "github.com/hashicorp/vault/api"
vaultutils "github.com/redhat-cop/vault-config-operator/api/v1alpha1/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -60,6 +65,35 @@ func (d *Policy) IsInitialized() bool {
}

func (d *Policy) PrepareInternalValues(context context.Context, object client.Object) error {
// Fast path escape if no "${..}" placeholder is detected
match, err := regexp.MatchString("\\${[^}]+}", d.Spec.Policy)
if err != nil || !match {
return nil
}

log := log.FromContext(context)

// Retrieves the list of auth engines to get their accessors
// Kinda duplicates logic found in VaultEngineObject.retrieveAccessor
vaultClient := context.Value("vaultClient").(*vault.Client)
secret, err := vaultClient.Logical().Read("sys/auth")
if err != nil {
// Log but ignore the error: do not resolve placeholders
log.Error(err, "could not resolve auth engine accessor(s) in policy rule - unable to retrieve auth engines at", "path", "sys/auth")
return nil
}
if secret == nil {
return errors.New("could not resolve auth engine accessor(s) in policy rule - listing auth engines at sys/auth unexpectedly returned null")
}

for key, data := range secret.Data {
authenginepath := strings.Trim(key, "/")
placeholder := "${auth/" + authenginepath + "/@accessor}"
accessor := data.(map[string]interface{})["accessor"].(string)
d.Spec.Policy = strings.ReplaceAll(d.Spec.Policy, placeholder, accessor)
}

log.Info("Auth engine accessor(s) resolved", "policy", d.Spec.Policy)
return nil
}

Expand Down
31 changes: 31 additions & 0 deletions docs/policy-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,39 @@ spec:
```
Notice that in this policy we have parametrized the path based on the namespace of the connecting service account.
This creates a policy at this path `/sys/policies/acl/<name>`

Automatically resolving an authentication engine accessor into a templated policy HCL can also be achieved for a more declarative style:
the operator will automatically replace all placeholders with format `${auth/<auth engine path>/@accessor}` with the accessor of the authentication
engine mounted at path `<auth engine path>`.

See [Vault Templated Policies](https://developer.hashicorp.com/vault/docs/concepts/policies#templated-policies) for more details on templated policies.

Note: the Vault role used for authentication (specified in the `authentication` section) must have `read` and `list` access
to Vault's `sys/auth` API endpoint for this automated resolution to work.

Any unresolved placeholder is left as-is into the configured policy.

The example above then becomes:

```yaml
apiVersion: redhatcop.redhat.io/v1alpha1
kind: Policy
metadata:
name: database-creds-reader
spec:
authentication:
path: kubernetes
role: policy-admin
policy: |
# Configure read secrets
path "/{{identity.entity.aliases.${auth/kubernetes/@accessor}.metadata.service_account_namespace}}/database/creds/+" {
capabilities = ["read"]
}
type: acl
```

## PasswordPolicy

The `PasswordPolicy` CRD allows a user to create a [Vault Password Policy](https://www.vaultproject.io/docs/concepts/password-policies), here is an example:
Expand Down

0 comments on commit 3d8d95b

Please sign in to comment.