Skip to content

Commit

Permalink
feat: add pentagon library (grafana#421)
Browse files Browse the repository at this point in the history
  • Loading branch information
Duologic authored Jan 19, 2021
1 parent fca1b13 commit 6aa643b
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 0 deletions.
24 changes: 24 additions & 0 deletions pentagon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Pentagon

This is a library to deploy [Grafana's fork of Pentagon](https://github.com/grafana/pentagon).

The library is intended to deploy 1 pentagon instance per namespace.

## Example

```
local pentagon = import 'pentagon/pentagon.libsonnet',
{
pentagon:
pentagon
+ pentagon.addPentagonMapping('secret/data/path/to/secret', 'kubernetes_secret_name')
+ pentagon.addPentagonMapping('secret/data/path/to/other_secret', 'kubernetes_other_secret_name')
+ {
_config+:: {
namespace: 'default',
cluster: 'prod',
},
},
}
```
67 changes: 67 additions & 0 deletions pentagon/config.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
local this = self,

_config+: {
namespace: error 'must define namespace',
cluster_name: error 'must define cluster_name',
pentagon+: {
name: 'pentagon',
refresh: '15m',
vault_address: error 'must provide vault_address',
vault_auth_path: 'auth/kubernetes/%s' % this._config.cluster_name,
vault_role: this._config.cluster_name,
},
},

_images+:: {
pentagon: 'grafana/pentagon:41',
},

pentagonKVMapping(path, secret):: {
vaultPath: path,
secretName: secret,
vaultEngineType: 'kv',
},

addPentagonMapping(path, secret, type='kv'):: {
pentagon_mappings_map+: {
[secret]+: {
vaultPath: path,
secretName: secret,
vaultEngineType: 'kv',
},
},
},

pentagon_mappings+:: [],
local pentagon_mappings_with_index = std.mapWithIndex(function(i, x) x { idx:: i }, this.pentagon_mappings),
pentagon_mappings_map+::
// a list like this.pentagon_mappings could have duplicates, using a map we can
// dedupe them base on a unique key (secretName in this case)
std.foldl(
function(obj, mapping)
obj {
[mapping.secretName]+: mapping,
},
pentagon_mappings_with_index,
{}
),

pentagonConfig:: {
vault: {
url: this._config.pentagon.vault_address,
authType: 'kubernetes',
authPath: this._config.pentagon.vault_auth_path,
defaultEngineType: 'kv',
role: this._config.pentagon.vault_role,
},
namespace: this._config.namespace,
label: this._config.pentagon.vault_role,
daemon: true,
refresh: this._config.pentagon.refresh,
mappings: std.sort([
this.pentagon_mappings_map[m]
for m in std.objectFields(this.pentagon_mappings_map)
], function(e) if std.objectHasAll(e, 'idx') then e.idx else 0),
},
}
15 changes: 15 additions & 0 deletions pentagon/jsonnetfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": 1,
"dependencies": [
{
"source": {
"git": {
"remote": "https://github.com/grafana/jsonnet-libs.git",
"subdir": "ksonnet-util"
}
},
"version": "master"
}
],
"legacyImports": true
}
99 changes: 99 additions & 0 deletions pentagon/pentagon.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
local kausal = import 'ksonnet-util/kausal.libsonnet';

(import 'config.libsonnet') +
{
local this = self,
local k = kausal { _config+:: this._config },

local container = k.core.v1.container,
local containerPort = k.core.v1.containerPort,
container::
container.new('pentagon', this._images.pentagon)
+ container.withImagePullPolicy('IfNotPresent')
+ container.withArgs([
'/etc/pentagon/pentagon.yaml',
])
+ container.withPorts([
containerPort.newNamed(name='http-metrics', containerPort=8888),
])
+ k.util.resourcesRequests('100m', '200Mi')
+ k.util.resourcesLimits('200m', '400Mi'),

local deployment = k.apps.v1.deployment,
deployment:
deployment.new(
'%(name)s-%(vault_role)s' % this._config.pentagon,
1,
[this.container]
) +
deployment.spec.template.spec.withServiceAccountName(this.rbac.service_account.metadata.name) +
k.util.configMapVolumeMount(this.config_map, '/etc/pentagon'),

withVaultCertFile(filename, configmap_name, hash=''):: {
pentagonConfig+:: {
vault+: {
tls+: {
// This needs to directly refer to a cert with `cacert`,
// using `capath` requires a run of c_rehash,
// which is much more complicated to implement
cacert: '/ssl/%s' % filename,
},
},
},
deployment+:
k.util.configVolumeMount(configmap_name, '/ssl')
+ (
if hash != ''
then deployment.spec.template.metadata.withAnnotationsMixin({
['%s-hash' % configmap_name]: hash,
})
else {}
),
},

local configMap = k.core.v1.configMap,
config_map:
configMap.new('%(name)s-%(vault_role)s' % this._config.pentagon)
+ configMap.withData({
'pentagon.yaml': k.util.manifestYaml(this.pentagonConfig),
}),

// rbac.service_account is used by pentagon for authenticating against Vault
// and updating k8s secrets.
local policyRule = k.rbac.v1.policyRule,
rbac:
k.util.namespacedRBAC(
this._config.pentagon.name,
[
policyRule.withApiGroups('')
+ policyRule.withResources(['secrets'])
+ policyRule.withVerbs(['get', 'list', 'watch', 'update', 'create', 'delete']),
]
),

local clusterRole = k.rbac.v1.clusterRole,
// clusterRole is needed to allow Vault to verify the token.
cluster_role:
clusterRole.new('%s-%s' % [this._config.pentagon.name, this._config.namespace])
+ clusterRole.withRulesMixin([
policyRule.withApiGroups('authentication.k8s.io')
+ policyRule.withResources(['tokenreviews'])
+ policyRule.withVerbs(['create']),

policyRule.withApiGroups('authentication.k8s.io')
+ policyRule.withResources(['subjectaccessreviews'])
+ policyRule.withVerbs(['create']),
]),

local clusterRoleBinding = k.rbac.v1.clusterRoleBinding,
cluster_role_binding:
clusterRoleBinding.new('%s-%s' % [this._config.pentagon.name, this._config.namespace])
+ clusterRoleBinding.roleRef.withApiGroup('rbac.authorization.k8s.io')
+ clusterRoleBinding.roleRef.withKind('ClusterRole')
+ clusterRoleBinding.roleRef.withName(this.cluster_role.metadata.name)
+ clusterRoleBinding.withSubjectsMixin({
kind: 'ServiceAccount',
name: this.rbac.service_account.metadata.name,
namespace: this.rbac.service_account.metadata.namespace,
}),
}

0 comments on commit 6aa643b

Please sign in to comment.