Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3745723
D2638.id6666.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
D2638.id6666.diff
View Options
diff --git a/_modules/credentials.py b/_modules/credentials.py
new file mode 100644
--- /dev/null
+++ b/_modules/credentials.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+
+# -------------------------------------------------------------
+# Salt — Credentials
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Credentials-related execution module methods
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+from salt.utils.files import fopen
+
+
+# -------------------------------------------------------------
+# HOF utilities
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+def _filter_discard_empty_string_values(haystack):
+ if type(haystack) is dict:
+ return {k: v for k, v in haystack.items() if v != ""}
+
+ if type(haystack) is list:
+ return [v for v in haystack if v != ""]
+
+ raise ValueError("Argument isn't a list or a dict: " + str(type(haystack)))
+
+
+def _join_document_fragments(fragments):
+ filtered = _filter_discard_empty_string_values(fragments)
+ return "\n\n".join(filtered)
+
+
+# -------------------------------------------------------------
+# Build Vault policies
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+class VaultSaltRolePolicy:
+ def __init__(self, role):
+ self.role = role
+
+ def build_policy(self):
+ return _join_document_fragments(
+ [
+ self.build_read_secrets_policy(),
+ self.import_extra_policies(),
+ ]
+ )
+
+ #
+ # Secrets from pillar entry vault_secrets_by_role
+ #
+
+ def build_read_secrets_policy(self):
+ vault_paths = __pillar__["vault_secrets_by_role"].get(self.role, [])
+
+ return _join_document_fragments(
+ [self.get_read_rule(vault_path) for vault_path in vault_paths]
+ )
+
+ @staticmethod
+ def get_read_rule(vault_path):
+ return f"""
+path \"{vault_path}\" {{
+ capabilities = [ \"read\" ]
+}}
+"""
+
+ #
+ # Import policies from pillar entry vault_extra_policies_by_role
+ #
+
+ def import_extra_policies(self):
+ extra_policies = __pillar__["vault_extra_policies_by_role"].get(self.role, [])
+ return _join_document_fragments(
+ [self.import_policy(policy) for policy in extra_policies]
+ )
+
+ @staticmethod
+ def import_policy(policy):
+ policy_file = f"{__pillar__['vault_policies_source']}/{policy}.hcl"
+ return f"# Import policy: {policy_file}"
+ # with fopen(policy_file) as fd:
+ # return fd.read()
+
+
+def _compile_roles_policies():
+ return {
+ role: VaultSaltRolePolicy(role).build_policy() for role in _get_relevant_roles()
+ }
+
+
+def _get_relevant_roles():
+ return {
+ role
+ for pillar_entry in [
+ "vault_extra_policies_by_role",
+ "vault_secrets_by_role",
+ ]
+ for role in __pillar__[pillar_entry].keys()
+ }
+
+
+def _build_node_policy(node, roles_policies):
+ rules = [
+ roles_policies[role]
+ for role in __salt__["node.get"]("roles", node)
+ if role in roles_policies
+ ]
+ return _join_document_fragments(rules)
+
+
+def build_policies_by_node():
+ roles_policies = _compile_roles_policies()
+
+ policies = {
+ node: _build_node_policy(node, roles_policies)
+ for node in __pillar__["nodes"].keys()
+ }
+
+ return _filter_discard_empty_string_values(policies)
diff --git a/_states/credentials.py b/_states/credentials.py
new file mode 100644
--- /dev/null
+++ b/_states/credentials.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+# -------------------------------------------------------------
+# Salt — Credentials state
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Allow to declare credentials-related states
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+from salt.states import vault
+from salt.utils.files import fopen
+
+
+def vault_policy_present(name, policy_file):
+ """
+ Ensure a Vault policy with the given name is present.
+
+ name
+ The name of the policy
+ policy_file
+ Path to a file on the minion containing rules,
+ formatted in HCL.
+
+ .. code-block:: yaml
+
+ demo_policy:
+ vault.policy_present:
+ - name: foo/bar
+ - policy_file: /opt/vault-policies/demo.hcl
+
+ """
+ with fopen(policy_file) as fd:
+ rules = fd.read()
+
+ return vault.policy_present(name, rules)
diff --git a/pillar/credentials/vault.sls b/pillar/credentials/vault.sls
new file mode 100644
--- /dev/null
+++ b/pillar/credentials/vault.sls
@@ -0,0 +1,113 @@
+# -------------------------------------------------------------
+# Salt configuration for Nasqueron servers
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: Trivial work, not eligible to copyright
+# -------------------------------------------------------------
+
+vault_policies_path: /srv/policies/vault
+vault_policies_source: salt://roles/vault/policies/files
+
+# -------------------------------------------------------------
+# Vault policies to deploy as-is, ie without templating.
+#
+# Entries of vault_policies must match a .hcl file in
+# roles/vault/policies/files folder.
+#
+# If you need a template, create a new pillar entry instead
+# and add the parsing logic either:
+# - directly to roles/vault/policies/
+#
+# - through _modules/credentials.py for policies to apply
+# to Salt nodes, like e.g. vault_secrets_by_role
+#
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+vault_policies:
+ - salt_primary
+
+# -------------------------------------------------------------
+# Vault policies for Salt
+#
+# Declare the extra policies each nodes need.
+#
+# In adition of those extra policies, the vault_secrets_by_role
+# will be parsed for the keys.
+#
+# IMPORTANT: as grains['roles'] can be modified by the node,
+# roles are extracted directly from the pillar.
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+vault_extra_policies_by_role:
+ salt-primary:
+ - salt_primary
+
+# -------------------------------------------------------------
+# Vault secrets by role
+#
+# Paths of the keys the specified role needs access to.
+#
+# Avoid * notation as this namespace is shared between Vault
+# and the applications. As such, only secrets the Salt nodes
+# needs in a state they need to deploy should be listed here.
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+vault_secrets_by_role:
+
+ opensearch:
+ - ops/secrets/nasqueron.opensearch.infra-logs.internal_users.admin
+ - ops/secrets/nasqueron.opensearch.infra-logs.internal_users.dashboards
+
+ paas-docker:
+
+ #
+ # Personal data or personally identifiable information (PII)
+ # related to Nasqueron Operations SIG members.
+ #
+
+ - ops/privacy/ops-cidr
+
+ #
+ # Credentials used by Nasqueron services
+ # Format: ops/secrets/nasqueron.<service>.<type>
+ #
+
+ - ops/secrets/nasqueron.acquisitariat.mysql
+
+ - ops/secrets/nasqueron.auth-grove.mysql
+
+ - ops/secrets/nasqueron.cachet.app_key
+ - ops/secrets/nasqueron.cachet.mysql
+
+ - ops/secrets/nasqueron.etherpad.api
+
+ - ops/secrets/nasqueron.notifications.broker
+ - ops/secrets/nasqueron.notifications.mailgun
+ - ops/secrets/nasqueron.notifications.sentry
+
+ - ops/secrets/nasqueron.pixelfed.app_key
+ - ops/secrets/nasqueron.pixelfed.mailgun
+ - ops/secrets/nasqueron.pixelfed.mysql
+
+ - ops/secrets/nasqueron.sentry.app_key
+ - ops/secrets/nasqueron.sentry.postgresql
+
+ #
+ # Credentials used by Nasqueron members private services
+ # Format: <username>.<service>.<type>
+ #
+
+ - ops/secrets/dereckson.phabricator.mysql
+
+ #
+ # Credentials used by projects hosted by Nasqueron
+ # Format: <project name>.<service>.<type>
+ #
+
+ - ops/secrets/espacewin.bugzilla.mysql
+
+ - ops/secrets/wolfplex.phabricator.mailgun
+ - ops/secrets/wolfplex.phabricator.mysql
+
+ - ops/secrets/zed.phabricator.mysql
+ - ops/secrets/zed.phabricator.sendgrid
diff --git a/pillar/nodes/nodes.sls b/pillar/nodes/nodes.sls
--- a/pillar/nodes/nodes.sls
+++ b/pillar/nodes/nodes.sls
@@ -44,6 +44,9 @@
hostname: complector.nasqueron.org
roles:
- vault
+ - salt-primary
+
+ # Deprecated, use salt-primary, a more inclusive terminology
- saltmaster
zfs:
pool: zroot
diff --git a/pillar/top.sls b/pillar/top.sls
--- a/pillar/top.sls
+++ b/pillar/top.sls
@@ -22,6 +22,9 @@
- opensearch.software
- opensearch.clusters
+ complector:
+ - credentials.vault
+
docker-001:
- credentials.zr
- paas.docker
diff --git a/roles/vault/init.sls b/roles/vault/init.sls
--- a/roles/vault/init.sls
+++ b/roles/vault/init.sls
@@ -7,3 +7,6 @@
include:
- .vault
+
+ # Depends of Vault installed
+ - .policies
diff --git a/roles/vault/policies/files/salt_primary.hcl b/roles/vault/policies/files/salt_primary.hcl
new file mode 100644
--- /dev/null
+++ b/roles/vault/policies/files/salt_primary.hcl
@@ -0,0 +1,26 @@
+# -------------------------------------------------------------
+# Vault configuration - Policy for salt primary server
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: Trivial work, not eligible to copyright
+# Source file: roles/vault/vault/files/salt_primary.hcl
+# -------------------------------------------------------------
+#
+# <auto-generated>
+# This file is managed by our rOPS SaltStack repository.
+#
+# Changes to this file may cause incorrect behavior
+# and will be lost if the state is redeployed.
+# </auto-generated>
+
+# -------------------------------------------------------------
+# Policies management
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+path "sys/policies/acl" {
+ capabilities = ["list"]
+}
+
+path "sys/policies/acl/*" {
+ capabilities = ["create", "read", "update", "delete", "list", "sudo"]
+}
diff --git a/roles/vault/policies/init.sls b/roles/vault/policies/init.sls
new file mode 100644
--- /dev/null
+++ b/roles/vault/policies/init.sls
@@ -0,0 +1,52 @@
+# -------------------------------------------------------------
+# Salt — Vault
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: Trivial work, not eligible to copyright
+# -------------------------------------------------------------
+
+{% set policies_path = pillar['vault_policies_path'] %}
+
+# -------------------------------------------------------------
+# Policies storage folder
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{{ policies_path }}:
+ file.directory:
+ - makedirs: True
+
+# -------------------------------------------------------------
+# Policies from vault_policies pillar entry
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{% for policy in pillar['vault_policies'] %}
+{% set policy_path = policies_path + "/" + policy + ".hcl" %}
+
+{{ policy_path }}:
+ file.managed:
+ - source: salt://roles/vault/policies/files/{{ policy }}.hcl
+
+vault_policy_{{ policy }}:
+ credentials.vault_policy_present:
+ - name: {{ policy }}
+ - policy_file: {{ policy_path }}
+ - onchanges:
+ - file: {{ policy_path }}
+
+{% endfor %}
+
+# -------------------------------------------------------------
+# Policies per nodes intended to be used through Salt
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{% for node, rules in salt['credentials.build_policies_by_node']().items() %}
+salt_node_{{ node }}:
+ vault.policy_present:
+ - rules: |
+ #
+ # <auto-generated>
+ # This policy is managed by our rOPS SaltStack repository.
+ # </auto-generated>
+ #
+ {{ rules | indent(8) }}
+{% endfor %}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 16, 16:40 (22 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2247791
Default Alt Text
D2638.id6666.diff (12 KB)
Attached To
Mode
D2638: Deploy policies for Vault
Attached
Detach File
Event Timeline
Log In to Comment